在我的另一篇文章《js typeof、instanceof区别一次给你讲明白》中讲过可以使用Object.prototype.toString
判断对象类型,而且是相比于typeof
和instanceof
更严谨的方式。
老实说,当时只知道可以这么用,为什么可以这么用,其中什么原理,我是一概不知。
这几天正好梳理原型相关的知识,碰到了这块内容,顺藤摸瓜竟然找到了答案,这里跟大家分享一下。
初识Object.prototype.toString
想找到原因,首先至少得搞清楚这个方法的定义和作用,我选择查询MDN,给大家贴一下地址:Object.prototype.toString。
其中对Object.prototype.toString
的解释如下:
每个对象都有一个 toString() 方法,当该对象被表示为一个文本值时,或者一个对象以预期的字符串方式引用时自动调用。默认情况下,toString() 方法被每个 Object 对象继承。如果此方法在自定义对象中未被覆盖,toString() 返回 “[object type]”,其中 type 是对象的类型。
其中type
是对象类型,但是这个type
是怎么判断的呢?我们还是不清楚。
好在文档里面列出了相关的一些规范:
我开始查看这些规范,希望从中找到更多关于Object.prototype.toString
的解释。
探秘JS规范
终于,皇天不负有心人,我从规范中看到了关键性的描述:
从这里我们知道,上面的type
就是这里提到的[[Class]]
,类似于这种命名往往都是JS的内部属性,我们只需找到它的定义即可。
找到了它的定义“The kind of this object”,貌似有点废话文学,不急我们继续查找。
这里解释了当执行new Object(value)
时到底发生了什么,而最后一步就包括将内部属性[[Class]]
设置成Object
。
我又看了new Number(value)
、new String(value)
、new Date(value)
等等,无一例外都是将[[Class]]
设置成构造器的名字。
而且,从规范中我们还能得知,[[Class]]
是无法被外部程序访问的。
豁然开朗
至于,我们明白了事情的来龙去脉。对象在创建之时,会用内部属性[[Class]]
记录对象创建时的类型,而且这个内部属性无法被外部程序访问,这意味着它很安全,Object.prototype.toString
就是利用这个内部属性来检测对象类型的。