徹底了解instanceof的底層實(shí)現(xiàn)原理

一、作用

①用于判斷某個(gè)實(shí)例是否屬于某構(gòu)造函數(shù)

②在繼承關(guān)系中用來(lái)判斷一個(gè)實(shí)例是否屬于它的父類(lèi)型或者祖先類(lèi)型的實(shí)例

說(shuō)白了,只要右邊變量的 prototype 在左邊變量的原型鏈上即可。因此,instanceof 在查找的過(guò)程中會(huì)遍歷左邊變量的原型鏈,直到找到右邊變量的 prototype,如果查找失敗,則會(huì)返回 false

二、語(yǔ)法

[對(duì)象] instanceof [構(gòu)造函數(shù)]

如:

var obj = new Object()

obj instanceof Object // true

三、涉及的構(gòu)造函數(shù)

基礎(chǔ)類(lèi)型:String、Number、Boolean、Undefined、Null、Symbol

復(fù)雜類(lèi)型:Array,Object

其他類(lèi)型:Function、RegExp、Date

四、底層原理

function instance_of(L, R) {

? ? var O = R.prototype;

? ? L = L.__proto__;

? ? while (true) {? ?

? ? ? ? if (L === null)? ? ?

? ? ? ? ? ? return false;?

? ? ? ? if (O === L)

? ? ? ? ? ? return true;?

? ? ? ? L = L.__proto__;?

? ? }

}

代碼解釋?zhuān)?/p>

①L表示對(duì)象實(shí)例,R表示構(gòu)造函數(shù)或者父類(lèi)型實(shí)例

②取R的顯式原型,取L的隱式原型

③循環(huán)遍歷,進(jìn)行判斷②中的兩個(gè)值是否相等,相等返回true,不相等繼續(xù)查找L的原型鏈

五、未發(fā)生繼承關(guān)系時(shí)

function Cat(name,age,type){

? ? this.name = name;

? ? this.age = age;

? ? this.type = type;

}

function Dog(name){

? ? this.name = name;

}

var cats = new Cat('有魚(yú)',2,'英短');

var dogs = new Dog('哈士奇');

console.log(cats instanceof Cat);? // true

console.log(dogs instanceof Dog);? // true

console.log(cats instanceof Object);? // true

console.log(dogs instanceof Object);? // true

先看一下“cats instanceof Cat”運(yùn)行情況:

function instance_of(L, R) { // L即cats? R即Cat

? ? var O = R.prototype; //O為Cat.prototype

? ? L = L.__proto__;? ? ? // L為cats._proto_

? ? while (true) {? ? //執(zhí)行循環(huán)

? ? ? ? if (L === null)? //不通過(guò)

? ? ? ? ? ? return false;?

? ? ? ? if (O === L)? ? ? //判斷:Cat.prototype ===cats._proto_

? ? ? ? ? ? ? ? return true;? //如果等于就返回true,證明cats是Cat類(lèi)型

? ? ? ? L = L.__proto__;?

? ? }

}

再看一下“cats instanceof Object”運(yùn)行情況:

function instance_of(L, R) { //L即cats? R即Object? ?

? ? var O = R.prototype;? //O為Object.prototype? ?

? ? L = L.__proto__;? ? // L為cats._proto_? ? ? ?

? ? while (true) {? ? //執(zhí)行循環(huán)? ? ?

? ? ? ? if (L === null)? //不通過(guò)?

? ? ? ? ? ? return false;? ? ?

? ? ? ? if (O === L)? // 此時(shí)判斷Object.prototype === cats._proto_ 顯然不成立

? ? ? ? ? ? return true;? ? ? ? ? ? ? ? ? ? ? ?

? ? ? ? L = L.__proto__;? //遍歷cats的原型鏈,即此時(shí)L為 cats._proto_ ._proto_,

? ? ? ? ? ? ? ? ? ? ? ? ? //即Cat.prototype._proto_指向的對(duì)象,

? ? ? ? ? ? ? ? ? ? ? ? //接著執(zhí)行循環(huán),

? ? ? ? ? ? ? ? ? ? ? ? //到Object .prototype === cats._proto_ ._proto_

? ? ? ? ? ? ? ? ? ? ? ? //成立,返回true

? ? }

}

六、產(chǎn)生繼承關(guān)系時(shí)

function Cat(name,age,type){

? ? this.name = name;

? ? this.age = age;

? ? this.type = type;

}

function YingDuan(name,age,type,sex){

? ? Cat.call(this,name,age,type);?

? ? this.sex = sex;

}

YingDuan.prototype = new Cat();? // 這里改變了原型指向,實(shí)現(xiàn)繼承

var yd = new YingDuan("有魚(yú)",2,"金漸層","男"); //創(chuàng)建了英短對(duì)象yd

console.log(yd instanceof YingDuan);? ? // true

console.log(yd instanceof Cat);? ? // true

console.log(yd instanceof Object);? ? // true

先看一下“yd instanceof YingDuan”運(yùn)行情況:

function instance_of(L, R) { //L即yd? R即YingDuan

? var O = R.prototype;? //O為YingDuan.prototype,現(xiàn)在指向了cat

? ? L = L.__proto__;? ? //L為yd._proto_,也隨著prototype的改變而指向了cat

? ? while (true) {? ? //執(zhí)行循環(huán)

? ? ? ? if (L === null)? //不通過(guò)

? ? ? ? ? ? return false;?

? ? ? ? if (O === L)? ? //判斷是否 YingDuan.prototype ===yd._proto_

? ? ? ? ? ? return true;? //此時(shí),兩方都指Cat的實(shí)例對(duì)象cat,所以true

? ? ? ? L = L.__proto__;? ? ?

? ? }

}

再看一下“yd instanceof Cat”運(yùn)行情況,即如何判斷yd繼承了Cat:

function instance_of(L, R) { // L即yd? R即Cat?

? var O = R.prototype; // O為Cat.prototype? ?

? ? L = L.__proto__;? //L為yd._proto_,現(xiàn)在指向的是cat實(shí)例對(duì)象

? ? while (true) {? // 執(zhí)行循環(huán)?

? ? ? if (L === null)? //不通過(guò)? ?

? ? ? ? ? return false;? ? ? ?

? ? ? if (O === L)? ? //判斷是否 Cat.prototype === yd._proto_?

? ? ? ? ? ? return true;? //此時(shí),yd._proto_ 指向cat實(shí)例對(duì)象,并不滿足

? ? ? ? L = L.__proto__;? //令L=? yd._proto_._proto_,執(zhí)行循環(huán)

? }? ? ? ? ? ? ? ? ? ? ? //yd._proto_ ._proto_,指的就是Cat.prototype,所以也返回true

}? ? ? ? ? ? ? ? ? ? ? ? //這就證明了yd繼承了Cat

yd instanceof Object也是同理的,這里暫不贅述。

七、注意問(wèn)題

instanceof 用于判斷對(duì)象類(lèi)型,但以下情況的結(jié)果都為false,請(qǐng)注意

console.log(Number instanceof Number)? // false

console.log(String instanceof String)? // false

console.log(Fun instanceof Fun)? ? ? ? // false,這里Fun指的是函數(shù)

console.log(null instanceof Object)? // false,null不具有任何對(duì)象的特性,也沒(méi)有__proto__屬性

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些閱讀 2,142評(píng)論 0 2
  • 前言 如果你要開(kāi)發(fā)一個(gè)復(fù)雜的產(chǎn)品,那么肯定少不了使用面向?qū)ο髾C(jī)制,當(dāng)然也避不開(kāi) Javascript 里面的繼承,...
    lifeColder閱讀 823評(píng)論 0 1
  • 如何控制alert中的換行?\n alert(“p\np”); 請(qǐng)編寫(xiě)一個(gè)JavaScript函數(shù) parseQu...
    heyunqiang99閱讀 1,147評(píng)論 0 6
  • 綠蟻新醅酒、紅泥小火爐,晚來(lái)天欲雪,能飲一杯無(wú)??吹疥幊恋奶?,就冒出了這首詩(shī),又是一年冬。 (一)冬日的吃 冬日,...
    沙棗花zyh閱讀 308評(píng)論 0 2
  • 剛畢業(yè)的時(shí)候覺(jué)得租房子也不錯(cuò),沒(méi)有想買(mǎi)房子的想法。 過(guò)了25歲,到了奔三的年齡,就越來(lái)越渴望有個(gè)家,屬于自己的房子...
    茶包與橙汁閱讀 271評(píng)論 1 0

友情鏈接更多精彩內(nèi)容