判斷數據類型的方式:
1. Object.prototype.toString
對象原型上的toString方法,在對象的this屬性上有可以判斷數據類型的隱藏屬性[[class]],其他的數據類型都有自己的toString方法,但是他們的toString方法被重寫了跟Object.prototype.toString不一樣。
比如:
(1)定義一個變量a是一個數字:var a = 1;
(2)a的類型:typeof a == "number";
(3)a調用toString方法:a.toString() == "1";
(4)爲什麼a是一個數字也可以調用toString方法呢?因爲:a.constructor == ƒ Number() { [native code] }; a 是由構造函數Number()new出來的;既然是構造函數構造出來,其實也可以看做是一個特殊的對象
(5)a的原型上是有toString方法,不過這個方法是重寫的,跟Object.prototype.toString的方法不一樣了。同樣的,數組、對象、布爾值等都重寫了toString方法
原型上包含了所有的方法,可以通過__proto__來查看這些方法,從而使用這些方法。
數組原型上也是:
注意:length: 0是原型的length屬性的值,arr有自己的length屬性,有自己的值。
(6)分別來看一下,不同類型的數據調用toString方法後的結果:
對象:
數組:
布爾值:
(7)除了對象調用toString方法得到的值判斷數據類型,其他的都是轉換爲字符串,當然,每個類型的toString實現的方式也是不同,比如:數組就是每一項都會調用toString方法,而得到的字符串。
(8)根據上面的變量a,可以調用toString方法,因爲構造函數內的this對象有一個 [[Class]] 隱藏的屬性(internal property),該屬性的值就是類型:
內部屬性 | 描述 |
---|---|
[[Class]] | 一個字符串值,表明了該對象的類型. |
只有最原始的對象的原型上的toString方法具有[[Class]]屬性,而該屬性正是來區分數據類型的,其他toString方法都被重寫了,失去了判斷類型的功能;正因爲如此,我們通過call來改變this指向,進而使得Object.prototype.toString.call()可以避開自己的toString方法,而去調用原型上的toString方法,才能確定數據類型。
(9)在toString方法被調用時,會執行下面的操作步驟:
獲取this對象的[[Class]]屬性的值.
計算出三個字符串"[object ", [[Class]]屬性的值, 以及 "]"連接後的新字符串.
返回計算的的結果
(10)在ES3中,規範文檔並沒有總結出[[class]]內部屬性一共有幾種,不過我們可以自己統計一下,原生對象的[[class]]內部屬性的值一共有10種.分別是:"Array", "Boolean", "Date", "Error", "Function", "Math", "Number", "Object", "RegExp", "String".
(11)ECMAScript 5,對象的[[Class]]屬性的值可以是除了"Arguments", "Array", "Boolean", "Date", "Error", "Function", "JSON", "Math", "Number", "Object", "RegExp", "String"之外的的任何字符串.
ES5的Object.prototype.toString ( )
在toString方法被調用時,會執行下面的操作步驟:
如果this的值爲undefined,則返回"[object Undefined]".
如果this的值爲null,則返回"[object Null]".
讓O成爲調用ToObject(this)的結果.
讓class成爲O的內部屬性[[Class]]的值.
返回三個字符串"[object ", class, 以及 "]"連接後的新字符串.
(12)Arguments類型
function func(a,b,c){
console.log(arguments);
console.log(Object.prototype.toString.call(arguments));
}
func(1,2,3);
結果:Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
[object Arguments]
2. 如果能明白toString方法的原理,還可以這麼寫:
var obj = {};
obj.toString.call([])
//結果
"[object Array]"
參考: