typeof實(shí)現(xiàn)原理
typeof 一般被用于判斷一個變量的類型, 我們可以利用typeof 來判斷 number, string, object, function, undefiend, symbol 這七種類型浑彰, 這種判斷能幫助我們搞定一些問題昼捍, 比如在判斷不是 object 類型的時(shí)候团驱,typeof能比較清楚的告訴我們具體是哪一種類型挣输。 但是刊驴, typeof在判斷object的數(shù)據(jù)的時(shí)候只能告訴我們這個數(shù)據(jù)時(shí)object, 不能細(xì)致到具體是哪一種object疮薇。
let str = new String('abc');
typeof str === 'object'; // true
s instanceof String // true
想要判斷是哪一種object 需要用 instanceof 這個操作符來判斷胸墙。
typeof 的原理
js在底層存儲數(shù)據(jù)類型信息的方式說明: 一個js變量在它的底層實(shí)現(xiàn)中,他的類型信息存儲變量會在機(jī)器碼的低位1-3存儲類型信息按咒。
- 000: 對象
- 010: 浮點(diǎn)數(shù)
- 100: 字符串
- 110: 布爾
- 1:整數(shù)
但是迟隅, 對于undefiend 和 null來說,這兩個值的信息存儲是有點(diǎn)獨(dú)特的励七。
- null: 所有機(jī)器碼均為 0
- undefiend: 用-2^30整數(shù)來表示
所以智袭, typeof 在判斷null的時(shí)候就會出現(xiàn)問題, 由于null的所有機(jī)器碼都是0掠抬, 因此直接被當(dāng)做了對象來處理吼野。
如果用instanceof 來判斷:
null instanceof null // TypeError: Right-hand side of 'instanceof' is not an object
null 由被判斷不是 object, 這也是 JavaScript的歷史遺留bug. (詳情了解typeof)
因此在用 typeof 來判斷變量類型的時(shí)候, 來判斷基本數(shù)據(jù)類型两波, 避免對 null 的判斷瞳步。
- 還有一個不錯的判斷類型的方法闷哆, 就是Object.prototype.toString, 此方法可以對一個變量類型進(jìn)行比較準(zhǔn)確的判斷。
Object.prototype.toString.call(1) // "[object Number]"
Object.prototype.toString.call('hi') // "[object String]"
Object.prototype.toString.call({a:'hi'}) // "[object Object]"
Object.prototype.toString.call([1,'a']) // "[object Array]"
Object.prototype.toString.call(true) // "[object Boolean]"
Object.prototype.toString.call(() => {}) // "[object Function]"
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call(undefined) // "[object Undefined]"
Object.prototype.toString.call(Symbol(1)) // "[object Symbol]"
instanceof 原理
instanceof 來判斷對象的具體類型是不準(zhǔn)確的单起, 其實(shí)instanceof 的主要作用就是判斷一個實(shí)例是否屬于某種類型
var Person = function() {};
var lee = new Person();
lee instanceof Person // true
當(dāng)然抱怔, instanceof 也可以判斷一個實(shí)例是否是其父類型或者祖先類型的實(shí)例。
var Parent = function() {};
var Child = function() {};
Child.prototype = new Parent();
var child = new Child();
child instanceof Child // true
child instanceof Parent // true
以上是 instanceof的用法嘀倒, 根據(jù)ECMAScript語言規(guī)范野蝇,梳理一下大概原理思路:
function new_instance_of(leftVaule, rightVaule) {
let rightProto = rightVaule.prototype; // 取右表達(dá)式的 prototype 值
leftVaule = leftVaule.__proto__; // 取左表達(dá)式的__proto__值
while (true) {
if (leftVaule === null) {
return false;
}
if (leftVaule === rightProto) {
return true;
}
leftVaule = leftVaule.__proto__;
}
}
其實(shí) instanceof主要思路就是只看右邊變量的 prototype在左邊變量的原型鏈上即可,因此括儒, instanceof 在查找過程中會遍歷左變量的原型鏈绕沈,直到找到等于右變量的 prototype,如果查找失敗帮寻,則會返回false, 查找成功返回true 告訴我們左邊變量是右邊變量的實(shí)例乍狐。
function Foo() {}
Object instanceof Object // true
Function instanceof Function // true
Function instanceof Object // true
Foo instanceof Foo // false
Foo instanceof Object // true
Foo instanceof Function // true
總結(jié)
- typeof判斷基本數(shù)據(jù)類型是ok的, 需要注意判斷 null類型時(shí)的問題固逗。
- 如果判斷一個類型是否屬于另一種類型可以使用 instanceof浅蚪。
- 如果需要準(zhǔn)確判斷對象實(shí)例的類型時(shí), 可以采取 Object.prototype.toString.call 方法烫罩。