平常我们判断某个变量类型的时候,会这样写:

var foo;
Object.prototype.toString.call(foo);
// "[object Undefined]"

今天手误,错写成了这样:

var foo;
Object.toString.call(foo);

// VM40:1 Uncaught TypeError: 
// Function.prototype.toString requires that 'this' be a Function
//  at toString (<anonymous>)
//  at toString (<anonymous>:1:765)
//  at <anonymous>:2:17

结果报错了,发生了什么?
提示我传入的 foo 应该是个 Function,但很明显 foo 是个 undefined。改一下试试看:

var foo = function(){};
Object.toString.call(foo);
// "function(){}"

这让我疑惑了,function(){} 这个结果应该是对一个函数调用 toString 的结果,于是:

var foo = function(){};
foo.toString();
// "function(){}"

果然,那是不是说明 Object.toStringFunction.toString 可能存在着某种关系,难道他们是一样的:

Object.toString == Function.toString
// true

原本以为 Object.toString == Object.prototype.toString 应该是 true,看来,有必要复习下 prototype 的相关知识点了。

那么,为什么 Object.toString == Function.toString 结果是 true 呢?我们先看下 ObjectFunction 分别是什么类型:

使用 Object.prototype.toString.call() 方式

Object.prototype.toString.call(Object)
// "[object Function]"
Object.prototype.toString.call(Function)
// "[object Function]"

也就是说, ObjectFunction 都是函数,调用其 toString 应该都是调用的 Function.prototype.toString,所以二者本质是一样的。

再来验证下

Object instanceof Function
// true
Function instanceof Function
// true
Object.constructor === Function
// true
Function.constructor === Function
// true

二者都是 Function 的实例,调用其 toString 方法,其本质都是调用构造函数 Function.prototype.toString

回到最开始的问题,Object.toString.call()Object.prototype.toString.call()有什么区别?

区别大了,前者调用的是 Object 构造函数 Function 的原型对象的 toString 方法,后者才真正调用的 Object 原型对象的 toString 方法,所以才导致了文章开头的异常。

文章最后,提醒自己,写代码要细心,少个字母大相径庭,做个严谨的工程师


lpicker
87 声望1 粉丝