深入理解Object.prototype.toString方法

深入理解Object.prototype.toString方法

ECMAScript 3

在toString方法被调用时,会执行下面的操作步骤:

  1. 获取this对象的[[Class]]属性的值.(第一步)

  2. 计算出三个字符串"[object ", 第一步的操作结果Result(1), 以及 "]"连接后的新字符串.(第二步)

  3. 返回第二步的操作结果Result(2). (第三步)

[[Class]]是一个内部属性,所有的对象(原生对象和宿主对象)都拥有该属性.在规范中,[[Class]]是这么定义的
[[Class]] 一个字符串值,表明了该对象的类型.
所有内置对象的[[Class]]属性的值是由本规范定义的.
所有宿主对象的[[Class]]属性的值可以是任意值,甚至可以是内置对象使用过的[[Class]]属性的值.
[[Class]]属性的值可以用来判断一个原生对象属于哪种内置类型.需要注意的是,除了通过Object.prototype.toString方法之外,本规范没有提供任何其他方式来让程序访问该属性的值。

ECMAScript 5

在ECMAScript 5中,Object.prototype.toString()被调用时,会进行如下步骤:
1 如果 this是undefined ,返回 [object Undefined] ;
2 如果 this是null , 返回 [object Null] ;
3 令 O 为以 this 作为参数调用 ToObject 的结果;
4 令 class 为 O 的内部属性 [[Class]] 的值;
5 返回三个字符串 “[object”, class, 以及"]" 拼接而成的字符串。

[[Class]]是一个内部属性,值为一个类型字符串,可以用来判断值的类型。
有这么一段详细的解释:
本规范的每种内置对象都定义了 [[Class]] 内部属性的值。宿主对象的 [[Class]] 内部属性的值可以是除了 "Arguments", "Array", "Boolean", "Date", "Error", "Function", "JSON", "Math", "Number", "Object", "RegExp", "String" 的任何字符串。[[Class]] 内部属性的值用于内部区分对象的种类。注,本规范中除了通过 Object.prototype.toString ( 见 15.2.4.2) 没有提供任何手段使程序访问此值。
在JavaScript代码里,唯一可以访问该属性的方法就是通过 Object.prototype.toString ,通常方法如下:

Object.prototype.toString.call(value)

可以用下列函数,来获取任意变量的[[Class]]属性:

function getClass (a) {
  const str = Object.prototype.toString.call(a)
  return /^\[object (.*)\]$/.exec(str)[1]
}

实例如下:

数据类型例子返回值
字符串“foo”.toString()“foo”
数字1.toString()Uncaught SyntaxError: Invalid or unexpected token
布尔值false.toString()“false”
undefinedundefined.toString()Uncaught TypeError: Cannot read property ‘toString’ of undefined
nullnull.toString()Uncaught TypeError: Cannot read property ‘toString’ of null
StringString.toString()“function String() { [native code] }”
NumberNumber.toString()“function Number() { [native code] }”
BooleanBoolean.toString()“function Boolean() { [native code] }”
ArrayArray.toString()“function Array() { [native code] }”
FunctionFunction.toString()“function Function() { [native code] }”
DateDate.toString()“function Date() { [native code] }”
RegExpRegExp.toString()“function RegExp() { [native code] }”
ErrorError.toString()“function Error() { [native code] }”
PromisePromise.toString()“function Promise() { [native code] }”
ObejctObject.toString()“function Object() { [native code] }”
MathMath.toString()“[object Math]”

ECMAScript 6

1 在ES6,调用 Object.prototype.toString 时,会进行如下步骤:
2 如果 this 是 undefined ,返回 ‘[object Undefined]’ ; (函数直接返回分支)
3 如果 this 是 null , 返回 ‘[object Null]’ ;(函数直接返回分支)
4 令 O 为以 this 作为参数调用 ToObject 的结果;(调用ToObject函数获取结果O)
5 令 isArray 为 IsArray(O) ;(调用IsArray(O) 函数获取结果赋值给isArray )
6 ReturnIfAbrupt(isArray) (如果 isArray 不是一个正常值,比如抛出一个错误,中断执行);
7 如果 isArray 为 true , 令 builtinTag 为 ‘Array’ ;
8 else ,如果 O is an exotic String object , 令 builtinTag 为 ‘String’ ;
9 else ,如果 O 含有 [[ParameterMap]] internal slot, , 令 builtinTag 为 ‘Arguments’ ;
10 else ,如果 O 含有 [[Call]] internal method , 令 builtinTag 为 Function ;
11 else ,如果 O 含有 [[ErrorData]] internal slot , 令 builtinTag 为 Error ;
12 else ,如果 O 含有 [[BooleanData]] internal slot , 令 builtinTag 为 Boolean ;
13 else ,如果 O 含有 [[NumberData]] internal slot , 令 builtinTag 为 Number ;
14 else ,如果 O 含有 [[DateValue]] internal slot , 令 builtinTag 为 Date ;
15 else ,如果 O 含有 [[RegExpMatcher]] internal slot , 令 builtinTag 为 RegExp ;
16 else , 令 builtinTag 为 Object ;
17 令 tag 为 Get(O, @@toStringTag) 的返回值( Get(O, @@toStringTag) 方法,既是在 O 是一个对象,并且具有 @@toStringTag 属性时,返回 O[Symbol.toStringTag] );
18 ReturnIfAbrupt(tag) ,如果 tag 是正常值,继续执行下一步;
如果 Type(tag) 不是一个字符串,let tag be builtinTag ;
19 返回由三个字符串 “[object”, tag, “]” 拼接而成的一个字符串。
注意:
1 步骤1,2是Object.prototype.toString(null)和Object.prototype.toString(undefined )的特殊入参的处理
2 步骤7到16是获取builtinTag变量的值;
3 步骤17的解释:

let obj = {}

Object.defineProperty(obj, Symbol.toStringTag, {
    get: function() {
        return "newClass"
    }
})

console.log(Object.prototype.toString.call(obj)) // "[object newClass]"

ECMAScript 7

ES7目前还是工作草案,到目前为止,就 Object.prototype.toString 的实现步骤来说, 只是移除了ES6其中的 ReturnIfAbrupt 。

附言

Object对象和它的原型链上各自有一个toString()方法,第一个返回的是一个函数,第二个返回的是值类型。

Object.toString.call(Array)//"function Array() { [native code] }"
Object.prototype.toString.call(Array)//"[object Function]"

Object.toString()//"function Object() { [native code] }"
Object.prototype.toString()//"[object Object]"
  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值