JS的typeof和instanceof
typeof
typeof操作符返回一個字符串,表示未經計算的操作數的類型。
就這么幾種類型:number、boolean、string、object、undefined、function、symbol。
typeof 1 // "number"
typeof '1' // "string"
typeof true // "boolean"
typeof Symbol(1) // "symbol"
typeof {} // "object"
typeof [] // "object",
typeof function(){} // "function"
typeof Symbol(1) // "symbol"
typeof undefined // "undefined"
typeof null // "object",
instanceof
instanceof 運算符用來測試一個對象在其原型鏈中是否存在一個構造函數的 prototype 屬性。
涉及的構造函數有這些基礎類型:String、Number、Boolean、Undefined、Null、Symbol;
復雜類型:Array,Object;
其他類型:Function、RegExp、Date。
語法:[對象] instanceof [構造函數],如:
let obj = new Object()
obj instanceof Object // true
注意左側必須是對象(object),如果不是,直接返回false,具體見基礎類型。
基礎類型
let num = 1
num instanceof Number // false
num = new Number(1)
num instanceof Number // true
明明都是num,而且都是1,只是因為第一個不是對象,是基本類型,所以直接返回false,而第二個是封裝成對象,所以true。
這里要嚴格注意這個問題,有些說法是檢測目標的__proto__與構造函數的prototype相同即返回true,這是不嚴謹的,檢測的一定要是對象才行,如:
let num = 1
num.__proto__ === Number.prototype // true
num instanceof Number // false
num = new Number(1)
num.__proto__ === Number.prototype // true
num instanceof Number // true
num.__proto__ === (new Number(1)).__proto__ // true
上面例子可以看出,1與new Number(1)幾乎是一樣的,只是區(qū)別在于是否封裝成對象,所以instanceof的結果是不同的。
string、boolean等,這些基礎類型一樣的。
new String(1)與String(1)是不同的,new是封裝成對象,而沒有new的只是基礎類型轉換,還是基礎類型,如下:
new String(1) // String {"1"}
String(1) // "1"
其他基礎類型一樣的。
復雜類型,比如數組與對象,甚至函數等,與基礎類型不同。
復雜類型
let arr = []
arr instanceof Array // true
arr instanceof Object // true
Array.isArray(arr) // true
首先,字面量是直接生成構造函數的,所以不會像基本類型一樣兩種情況,這個可以放心用。
但是上面那個問題,當然,基礎類型也會有這個問題,就是與Object對比。沒辦法,Object在原型鏈的上層,所以都會返回true,如下:
(new Number(1)) instanceof Object // true
由于從下往上,比如你判斷是Number,那就沒必要判斷是不是Object了,因為已經是Number了……
Array一個道理,不過還是建議使用isArray來專門處理數組判斷。
new Object()與{}就不介紹了,一樣的情況。
其他類型
let reg = new RegExp(//)
reg instanceof RegExp // true
reg instanceof Object // true
let date = new Date()
date instanceof Date // true
date instanceof Object // true
除了Function,都一樣,具體Function如下:
function A() {}
let a = new A()
a instanceof Function // false
a instanceof Object // true
A instanceof Function // true
這里要注意,function A() {}相當于let A; A = function() {},然后分析:
- a是new出來,所以是經過構造,因此已經是對象,不再是函數,所以false。
- a是經過構造的對象,返回ture沒問題。
- 如上所述,A是個函數,因此沒什么概念上的問題。但是要知道
A.__proto__即Function.prototype是? () { [native code] },這是與object以后處于原型鏈上層的存在,而且與object平級,檢測如下:
let obj = {}
obj.__proto__ // {constructor: ?, __defineGetter__: ?, __defineSetter__: ?, hasOwnProperty: ?, __lookupGetter__: ?, …}
obj.__proto__.prototype // undefined
let A = function() {}
A.__proto__ // ? () { [native code] }
A.__proto__.prototype // undefined