Principles of the Object.prototype.toString method in JavaScript

  • 2021-01-02 21:46:15
  • OfStack

In JavaScript, the most reliable way to determine which built-in type an object value belongs to is through the Object.prototype.toString method.


var arr = [];
console.log(Object.prototype.toString.call(arr)) //"[object Array]"

In this article, I'll show you how the toString method does this and how it works.

ECMAScript 3

In ES3, the specification for the ES15en.prototype.toString method is as follows:


15.2.4.2 Object.prototype.toString()

When the toString method is called, the following steps are performed:

1. Gets the value of the [[Class]] attribute of the this object.

2. Calculate the three strings "[object ", the result of step 1, Result(1), and the new string after the concatenation of "]".

3. Return the operation result of Step 2, Result(2).

[[Class]] is an internal property that is owned by all objects (native and host objects). In the specification,[[Class]] is defined this way

内部属性 描述
[[Class]] 1个字符串值,表明了该对象的类型.

Then he gave a paragraph of explanation:

The value of the [[Class]] attribute of all built-in objects is defined by this specification. The value of the [[Class]] attribute of all host objects can be any value, or even the value of the [[Class]] attribute used by the built-in object. The value of the [[Class]] attribute can be used to determine which built-in type a native object belongs to. It is important to note that this specification does not provide any means for programs to access the value of this property other than through the Object.prototype.toString method (see 15.2.4.2).

In other words, by removing the string returned by the Object.prototype.toString method and the fixed "[object "before and the fixed "]" after it, the value of the internal attribute [[class]] is the value of the object type.

In ES3, the specification document does not summarize [[class]] internal attribute 1, but we can count 1 for ourselves, there are 10 values of [[class]] internal attribute 1 for native objects. Respectively is: "Array Boolean", ""," Date ", "Error", "Function", "Math", "Number", "Object", "RegExp", "String".

ECMAScript 5

In addition to the specification written in more detail in ES5.1, the definition of the Object.prototype.toString method and [[class]] internal properties have also been changed. The specification for Object.prototype.toString method is as follows:

15.2.4.2 Object.prototype.toString ( )

When the toString method is called, the following steps are performed:

If the value of this is undefined, "[object Undefined]" is returned.

If the value of this is null, "[object Null]" is returned.

Make O the result of calling ToObject(this).

Make class the value of the internal property [[Class]] of O.

Returns three strings "[object ", class, and "]" concatenated to create a new string.

It can be seen that there are 1,2 and 3 more steps than ES3. Step 1 and 2 belong to the new rule and are special because "Undefined" and "Null" are not values of the [[class]] attribute. It should be noted that this has nothing to do with strict mode (most functions in strict mode keep the value of this or null, but become global objects automatically in non-strict mode). Step 3 is not a new rule, because in the ES3 engine, this step converts the three primitive value types to the corresponding wrapper objects, but it is not written in the specification.

The value of the [[Class]] attribute of all built-in objects is defined by this specification. The [[Class]] attributes of all host objects can be values other than "Arguments", "Array", "Boolean", "Date", "Error", "Function", "Math", "Number", "RegExp", Any string other than "String".[[Class]] internal properties are used within the engine to determine what type of value an object belongs to. It is important to note that this specification does not provide any means for programs to access the value of this property other than through the ES154en.prototype.toString method (see 15.2.4.2).

Compared to ES3, the first difference is that [[class]] has two more internal attributes (12), one is that [[class]] of the arguments object becomes "Arguments" instead of "Object", and there are multiple global objects (JSON) whose [[class]] value is "JSON". The second difference is that the value of the [[class]] internal property of the host object cannot conflict with these 12 values, although none of the ES3 supported browsers seem to have found any host objects that intentionally use those 10 values.

ECMAScript 6

ES6 is only a working draft at the moment, but it is certain that the [[class]] internal attribute has been replaced by another [[NativeBrand]].[[NativeBrand]] attribute is defined as follows:

内部属性 属性值 描述
[[NativeBrand]] 枚举NativeBrand的1个成员. 该属性的值对应1个标志值(tag value),可以用来区分原生对象的类型.

[[NativeBrand]] attribute interpretation:

[[NativeBrand]] the internal attribute is used to identify whether a native object is an object of a particular type that conforms to this specification.[[NativeBrand]] The value of the internal attribute is one of the following enumerated types :NativeFunction, NativeArray, StringWrapper, BooleanWrapper, NumberWrapper, NativeMath, NativeDate, NativeRegExp, NativeJSON, NativeArguments, NativePrivateName.[[NativeBrand]] internal attributes are used only to distinguish between specific types of ECMAScript native objects. Only the object types specified in Table 10 have [[NativeBrand]] internal attributes.

Table 10 -- [[NativeBrand]] values for internal attributes

属性值 对应类型
NativeFunction Function objects
NativeArray Array objects
StringWrapper String objects
BooleanWrapper Boolean objects
NumberWrapper Number objects
NativeMath The Math object
NativeDate Date objects
NativeRegExp RegExp objects
NativeError Error objects
NativeJSON The JSON object
NativeArguments Arguments objects
NativePrivateName Private Name objects

As you can see, unlike [[class]], not every object has [[NativeBrand]]. At the same time, the specification of Object. prototype. toString method has also been changed as follows:

15.2.4.2 Object.prototype.toString ( )

When the toString method is called, the following steps are performed:

If the value of this is undefined, then "[object Undefined]" is returned.

If the value of this is null, "[object Null]" is returned.

Make O the result of calling ToObject(this).

If O has the [[NativeBrand]] internal attribute, make tag the corresponding value in Table 29.

Otherwise,

Make hasTag the result of calling the [[HasProperty]] internal method of O with the parameter @@toStringTag.

If hasTag is false, make tag "Object".

Otherwise,

Make tag the result of calling the [[Get]] internal method of O with the argument @@toStringTag.

If tag is 1 abrupt completion, make tag NormalCompletion("? The & # 63; The & # 63;" ).

Make tag tag.[[value]].

If Type(tag) is not a string, make tag "? The & # 63; The & # 63;" .

If the value of tag is "Arguments", "Array", "Boolean", "Date", "Error", "Function", "JSON", "Math", "Number", "Object", "RegExp", or

If any of "String", then tag becomes the result of the string "~" concatenated with the current value of tag.

Returns 3 strings "[object ", tag, and "]" concatenated to create a new string.

Table 29 -- [[NativeBrand]] flag values

[[NativeBrand]]值 标志值
NativeFunction "Function"
NativeArray "Array"
StringWrapper "String"
BooleanWrapper "Boolean"
NumberWrapper "Number"
NativeMath "Math"
NativeDate "Date"
NativeRegExp "RegExp"
NativeError "Error"
NativeJSON "JSON"
NativeArguments "Arguments"

As you can see, there have been a lot of changes in the specification, but to the average user, it doesn't seem to be noticeable.

Perhaps you have noticed that the new types in ES6, Map,Set, etc., are not in Table 29. What do they return when they execute the toString method ?


console.log(Object.prototype.toString.call(Map())) //"[object Map]"
console.log(Object.prototype.toString.call(Set())) //"[object Set]"

Where does the string "Map" come from:

15.14.5.13 Map.prototype.@@toStringTag

The initial value of the @toStringTag attribute is the string "Map".

As the ES6 specification is still being developed, various regulations are subject to change, so if you want to know more details. Looking at the following two links, all you need to know for now is that [[class]] is gone, using a more complex mechanism.

Above is the principle of Object. prototype. toString method shared by this site, I hope it will be helpful to you!


Related articles: