平常我們判斷某個變量類型的時候,會這樣寫:
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.toString 跟 Function.toString 可能存在着某種關係,難道他們是一樣的:
Object.toString == Function.toString
// true
原本以為 Object.toString == Object.prototype.toString 應該是 true,看來,有必要複習下 prototype 的相關知識點了。
那麼,為什麼 Object.toString == Function.toString 結果是 true 呢?我們先看下 Object、Function 分別是什麼類型:
使用 Object.prototype.toString.call() 方式
Object.prototype.toString.call(Object)
// "[object Function]"
Object.prototype.toString.call(Function)
// "[object Function]"
也就是説, Object、Function 都是函數,調用其 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 方法,所以才導致了文章開頭的異常。
文章最後,提醒自己,寫代碼要細心,少個字母大相徑庭,做個嚴謹的工程師