摘要:代碼傳送門(mén)如上代碼示例,從其運(yùn)行結(jié)果可知,是等于的原型的,是被對(duì)象后返回的函數(shù),從驗(yàn)證結(jié)果來(lái)看,函數(shù)經(jīng)過(guò)的一層包裝,依然不會(huì)影響其原型檢測(cè)的綁定。
前言
在面向?qū)ο笳Z(yǔ)言中,一般都有關(guān)鍵字 instanceof 來(lái)檢測(cè)對(duì)象類(lèi)型,更準(zhǔn)確點(diǎn)來(lái)說(shuō)是檢測(cè)對(duì)象是哪個(gè)類(lèi)型的實(shí)例。那么在 JS 中這個(gè)關(guān)鍵字又有什么不同之處呢?此文僅是一篇對(duì) ES 標(biāo)準(zhǔn)中 instanceof 關(guān)鍵字的解讀,并記錄了在此過(guò)程中的對(duì) JS 中對(duì)象系統(tǒng)的一點(diǎn)小感悟。
標(biāo)準(zhǔn)規(guī)定該關(guān)鍵字需要做什么
先舉例 a instanceof b, 下文中的步驟解釋中關(guān)鍵字左側(cè)的值用a表示, 右側(cè)的值用b表示。
在標(biāo)準(zhǔn)中 instanceof 的行為被抽象到 InstanceofOperator 操作中,下面列出比較關(guān)鍵的兩個(gè)抽象操作,并根據(jù)自己的理解對(duì)整理了下步驟:
InstanceofOperator ( a, b);
OrdinaryHasInstance ( b, a );
InstanceofOperator ( a, b)
檢測(cè)b是否是對(duì)象,否TypeError
獲取b是否定義了Symbol.hasInstance
是則bSymbol.hasInstance,返回true或false
否則判斷b是否是函數(shù),否則TypeError
是則返回OrdinaryHasInstance(b, a)的運(yùn)行結(jié)果
OrdinaryHasInstance ( b, a )
判斷b是否是函數(shù),否則返回false(這一步在這一場(chǎng)景中應(yīng)該不會(huì)被調(diào)用)
是則判斷b是否是被bind包裝過(guò)的函數(shù),是則獲取到bind包裝的函數(shù)bc,并調(diào)用InstanceofOperator( a, bc)
是則檢測(cè)a是否是對(duì)象,否則返回false
是則獲取b的prototype屬性bp
如果bp不是對(duì)象則返回TypeError
獲取a的原型并賦值給a
檢測(cè)a是否為null,是則返回false
否則判斷a和bp是否相等,是則返回true
否則重復(fù)步驟11~14直至返回true或false
幾處細(xì)節(jié)的推敲
在查看標(biāo)準(zhǔn)解釋是,有幾處理解的不是很明白,故使用幾個(gè)demo對(duì)自己的理解做了驗(yàn)證
b應(yīng)該是什么值
先看b不是對(duì)象是什么情況
從上面的結(jié)果可以看到報(bào)錯(cuò)了,而且錯(cuò)誤提示很明顯的提示右側(cè)的值不是對(duì)象,這是第1步檢測(cè)報(bào)的錯(cuò),那么如果是對(duì)象,而不是函數(shù)對(duì)象又會(huì)是什么情況呢?
嗯,沒(méi)錯(cuò),對(duì)象也報(bào)錯(cuò)了,這次的錯(cuò)誤是右側(cè)的值不可調(diào)用,即不是函數(shù),這應(yīng)是第4步檢測(cè)報(bào)的錯(cuò)了。根據(jù)上面的步驟試試給對(duì)象設(shè)置Symbol.hasInstance屬性
這一次沒(méi)有報(bào)錯(cuò),檢測(cè)正常進(jìn)行了,且返回了在函數(shù)中定義的結(jié)果,根據(jù)上面的步驟和代碼驗(yàn)證,可以得出右側(cè)的值可以是設(shè)置了Symbol.hasInstance屬性的對(duì)象。且檢測(cè)的結(jié)果會(huì)被右側(cè)值定義的Symbol.hasInsyance函數(shù)攔截成函數(shù)返回的結(jié)果。
右側(cè)是函數(shù)的情況就是比覺(jué)正常的返回了,需要明確的一點(diǎn)是函數(shù)是不能直接設(shè)置Symbol.hasInstance屬性的,具體原因,感興趣的可以繼續(xù)查閱資料。到這里可以得出結(jié)論,b必須是設(shè)置了Symbol的對(duì)象或者函數(shù),否則會(huì)報(bào)錯(cuò)。
被 dind 包裝過(guò)的函數(shù)依然會(huì)返回原函數(shù)原型檢測(cè)結(jié)果
這一步存疑的原因是,沒(méi)有直接理解標(biāo)準(zhǔn)中的描述,只是有所猜測(cè),不能確定,故驗(yàn)證之。
var a = function() { this.name = "a"; }; var b = {testName: "b"}; a.prototype = b; var c = new a(); console.log("c instanceof a", c instanceof a); // true var h = {name: "h"}; var s = a.bind(h); console.log("c instanceof s", c instanceof s); // true
代碼傳送門(mén)
如上代碼示例,從其運(yùn)行結(jié)果可知,a.prototype 是等于 c 的原型的,s 是 a 被 bind 對(duì)象 h 后返回的函數(shù),從驗(yàn)證結(jié)果來(lái)看,函數(shù)經(jīng)過(guò) bind 的一層包裝,依然不會(huì)影響其原型檢測(cè)的綁定。
一點(diǎn)思考
在推敲上面細(xì)節(jié)時(shí)突然聯(lián)想到這種檢測(cè)實(shí)際是很合理的,類(lèi)比 Java 中的檢測(cè)類(lèi),這里對(duì)象的原型不就可以類(lèi)比成 Java 里面的類(lèi)么。 某個(gè)對(duì)象的原型是什么決定它具備了原型對(duì)象的特性的,而類(lèi)不也是這樣么,該對(duì)象屬于哪個(gè)類(lèi),決定了該對(duì)象具備了哪些特性。不同的是,在JS中的檢測(cè)是往繼承鏈上多退了一步的,Java 中是直接檢測(cè)對(duì)象是否是該類(lèi)的實(shí)例,而JS中是檢測(cè)的是對(duì)象的原型是否等于函數(shù)的prototype屬性,這應(yīng)該就是繼承原理不同產(chǎn)生的區(qū)別吧。
之前從未認(rèn)真的思考過(guò),JS 中的整個(gè)對(duì)象系統(tǒng)是什么樣的,雖然現(xiàn)在也還是沒(méi)有理解太多,但是至少現(xiàn)在在我的認(rèn)知里 JS 的 對(duì)象系統(tǒng)是簡(jiǎn)單而完善的,并沒(méi)有因?yàn)楹?jiǎn)單而缺少了面向?qū)ο蠡咎匦浴km然它靈活的允許你隨便更改一個(gè)對(duì)象的原型,也就是類(lèi),但是這依然不妨礙它成為一門(mén)可以面像對(duì)象編程的語(yǔ)言。
結(jié)論
instanceof 關(guān)鍵字檢測(cè)的本質(zhì)是檢測(cè)左側(cè)對(duì)象的原型鏈上是否存在和右側(cè)函數(shù)的prototype屬性相等的對(duì)象,如果存在則返回true,如果不存在則返回false。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/6703.html
摘要:模式閱讀筆記第一部分函數(shù)模式總的來(lái)說(shuō)模式是一本力薦的進(jìn)階書(shū)書(shū)里面涉及了很多在學(xué)習(xí)過(guò)程中會(huì)碰到的坑然后提供了很不錯(cuò)的解決方法雖然很多人吐槽這本書(shū)的翻譯但是糟糕的翻譯還是無(wú)法掩蓋這是一本好書(shū)的事實(shí)因此這里我會(huì)結(jié)合書(shū)上的知識(shí)和我的理解來(lái)寫(xiě)一些 Javascript模式 閱讀筆記-第一部分-函數(shù)模式 總的來(lái)說(shuō),javascript模式是一本力薦的js進(jìn)階書(shū),書(shū)里面涉及了很多在學(xué)習(xí)javascr...
摘要:怎么樣才能把項(xiàng)目做的好一點(diǎn)或者更好首先,在老板看來(lái),他肯定希望今天提的需求可以立馬就上線。關(guān)于注釋注釋是有必要的,這個(gè)對(duì)個(gè)人和他人都是有好處的。 之前做開(kāi)發(fā)的時(shí)候?qū)?xiàng)目完全沒(méi)有一個(gè)整體的思考,需求來(lái)了就知道做,只關(guān)心自己做的那部分的功能,做完拉到。但最近所做的項(xiàng)目中,遇到了不少問(wèn)題,自己都忍不住吐槽起來(lái)了。如:項(xiàng)目經(jīng)常性延期、代碼冗余、添加一個(gè)很小的新功能都需要改動(dòng)很多地方,還對(duì)之前的...
摘要:怎么樣才能把項(xiàng)目做的好一點(diǎn)或者更好首先,在老板看來(lái),他肯定希望今天提的需求可以立馬就上線。關(guān)于注釋注釋是有必要的,這個(gè)對(duì)個(gè)人和他人都是有好處的。 之前做開(kāi)發(fā)的時(shí)候?qū)?xiàng)目完全沒(méi)有一個(gè)整體的思考,需求來(lái)了就知道做,只關(guān)心自己做的那部分的功能,做完拉到。但最近所做的項(xiàng)目中,遇到了不少問(wèn)題,自己都忍不住吐槽起來(lái)了。如:項(xiàng)目經(jīng)常性延期、代碼冗余、添加一個(gè)很小的新功能都需要改動(dòng)很多地方,還對(duì)之前的...
摘要:事件只能攜帶一個(gè)的。例如在上述代碼示例中的將所有使用發(fā)布事件的地方,全部修改為使用的方法。是否能夠編寫(xiě)腳本或者自動(dòng)化工具,自動(dòng)化的完成重構(gòu)工作。實(shí)施方案使用注解解析自動(dòng)生成文件我們都知道,是通過(guò)注解來(lái)實(shí)現(xiàn)的。 歡迎大家前往騰訊云社區(qū),獲取更多騰訊海量技術(shù)實(shí)踐干貨哦~ 作者:吳濤 導(dǎo)語(yǔ):EventBus 已經(jīng)火了很長(zhǎng)一段時(shí)間了。最近我們項(xiàng)目決定引入EventBus,替換我們播放器現(xiàn)在的事...
閱讀 3616·2021-11-23 09:51
閱讀 1493·2021-11-04 16:08
閱讀 3561·2021-09-02 09:54
閱讀 3626·2019-08-30 15:55
閱讀 2607·2019-08-30 15:54
閱讀 967·2019-08-29 16:30
閱讀 2057·2019-08-29 16:15
閱讀 2328·2019-08-29 14:05