摘要:今天同事小英童鞋問了我一個(gè)問題小英童鞋認(rèn)為的原型對象是,所以會(huì)繼承的屬性,調(diào)用相當(dāng)于調(diào)用,但結(jié)果不是一個(gè)方法。構(gòu)造函數(shù)創(chuàng)建對象實(shí)例函數(shù)有兩個(gè)不同的內(nèi)部方法和。如果不通過關(guān)鍵字調(diào)用函數(shù),則執(zhí)行函數(shù),從而直接執(zhí)行代碼中的函數(shù)體。
今天同事小英童鞋問了我一個(gè)問題:
function Foo(firstName, lastName){ this.firstName = firstName; this.lastName = lastName; } Foo.prototype.logName = function(){ Foo.combineName(); console.log(this.fullName); } Foo.prototype.combineName = function(){ this.fullName = `${this.firstName} ${this.lastName}` } var foo = new Foo("Sanfeng", "Zhang"); foo.logName(); // Uncaught TypeError: Foo.combineName is not a function
小英童鞋認(rèn)為Foo的原型對象是Foo.prototype,所以Foo會(huì)繼承Foo.prototype的屬性,調(diào)用Foo.combineName()相當(dāng)于調(diào)用Foo.prototype.combineName(),但結(jié)果Foo.combineName()不是一個(gè)方法。
會(huì)造成這個(gè)問題的原因一定是因?yàn)樾∮⑼炝嗽秃屠^承的一些原理,下面我們來整理一下原型和繼承的相關(guān)原理,找出問題的根本原因。
prototypeprototype是一個(gè)擁有 [[Construct]] 內(nèi)部方法的對象才有的屬性。
例如函數(shù),對象的方法,ES6 中的類。注意 ES6 中的箭頭函數(shù)沒有 [[Construct]] 方法,因此沒有prototype這個(gè)屬性,除非你為它添加一個(gè)。
當(dāng)創(chuàng)建函數(shù)時(shí),JavaScript 會(huì)為這個(gè)函數(shù)自動(dòng)添加prototype屬性,這個(gè)屬性指向的是一個(gè)原型對象Functionname.prototype。我們可以向這個(gè)原型對象添加屬性或?qū)ο螅踔量梢灾赶蛞粋€(gè)現(xiàn)有的對象。
__proto__接下來我們說說繼承,每個(gè)對象都有一個(gè)__proto__屬性,這個(gè)屬性是用來標(biāo)識(shí)自己所繼承的原型。
注意: JavaScript 中任意對象都有一個(gè)內(nèi)置屬性 [[Prototype]] ,在ES5之前沒有標(biāo)準(zhǔn)的方法訪問這個(gè)內(nèi)置屬性,但是大多數(shù)瀏覽器都支持通過__proto__來訪問。以下統(tǒng)一使用__proto__來訪問 [[Prototype]],在實(shí)際開發(fā)中是不能這樣訪問的。
原型鏈JavaScript 可以通過prototype和__proto__在兩個(gè)對象之間創(chuàng)建一個(gè)關(guān)聯(lián),使得一個(gè)對象就可以通過委托訪問另一個(gè)對象的屬性和函數(shù)。
這樣的一個(gè)關(guān)聯(lián)就是原型鏈,一個(gè)由對象組成的有限對象鏈,用于實(shí)現(xiàn)繼承和共享屬性。
構(gòu)造函數(shù)創(chuàng)建對象實(shí)例JavaScript 函數(shù)有兩個(gè)不同的內(nèi)部方法:[[Call]] 和 [[Construct]] 。
如果不通過new關(guān)鍵字調(diào)用函數(shù),則執(zhí)行 [[Call]] 函數(shù),從而直接執(zhí)行代碼中的函數(shù)體。
當(dāng)通過new關(guān)鍵字調(diào)用函數(shù)時(shí),執(zhí)行的是 [[Construct]] 函數(shù),它負(fù)責(zé)創(chuàng)建一個(gè)實(shí)例對象,把實(shí)例對象的__proto__屬性指向構(gòu)造函數(shù)的prototype來實(shí)現(xiàn)繼承構(gòu)造函數(shù)prototype的所有屬性和方法,將this綁定到實(shí)例上,然后再執(zhí)行函數(shù)體。
模擬一個(gè)構(gòu)造函數(shù):
function createObject(proto) { if (!(proto === null || typeof proto === "object" || typeof proto === "function"){ throw TypeError("Argument must be an object, or null"); } var obj = new Object(); obj.__proto__ = proto; return obj; } var foo = createObject(Foo.prototype);
至此我們了解了prototype和__proto__的作用,也了解使用構(gòu)造函數(shù)創(chuàng)建對象實(shí)例時(shí)這兩個(gè)屬性的指向,以下使用一張圖來總結(jié)一下如何通過prototype和__proto__實(shí)現(xiàn)原型鏈。
從上圖我們可以找出foo對象和Foo函數(shù)的原型鏈:
foo.__proto__ == Foo.prototype; foo.__proto__.__proto__ == Foo.prototype.__proto__ == Object.prototype; foo.__proto__.__proto__.__proto__ == Foo.prototype.__proto__.__proto__ == Object.prototype.__proto__ == null;
Foo.__proto__ == Function.prototype; Foo.__proto__.__proto__ == Function.prototype.__proto__; Foo.__proto__.__proto__.__proto__ == Function.prototype.__proto__.__proto__ == Object.prototype.__proto__ == null;
構(gòu)造函數(shù)Foo的原型鏈上沒有Foo.prototype,因此無法繼承Foo.prototype上的屬性和方法。而實(shí)例foo的原型鏈上有Foo.prototype,因此foo可以繼承Foo.prototype上的屬性和方法。
到這里,我們可以很簡單的解答小英童鞋的問題了,在Foo的原型鏈上沒有Foo.prototype,無法繼承Foo.prototype上的combineName方法,因此會(huì)拋出Foo.combineName is not a function的異常。要想使用combineName方法,可以這樣Foo.prototype.combineName.call(this),或者這樣this.combineName()(this指向?qū)嵗龑ο螅?/p>
歡迎關(guān)注:Leechikit
原文鏈接:segmentfault.com到此本文結(jié)束,歡迎提問和指正。
寫原創(chuàng)文章不易,若本文對你有幫助,請點(diǎn)贊、推薦和關(guān)注作者支持。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/92015.html
摘要:的英文含義是名單種技術(shù)的確都是把當(dāng)做清單使用緩存清單清單打包資源路徑清單打包清單只不過是在不同的場景中使用特定的清單來完成某些功能所以,學(xué)好英文是多么重要,這樣才不會(huì)傻傻分不清到底是干啥的 在前端,說到manifest,其實(shí)是有歧義的,就我了解的情況來說,manifest可以指代下列含義: html標(biāo)簽的manifest屬性: 離線緩存(目前已被廢棄) PWA: 將Web應(yīng)用程序...
摘要:當(dāng)這步完成,這個(gè)對象就與構(gòu)造函數(shù)再無聯(lián)系,這個(gè)時(shí)候即使構(gòu)造函數(shù)再加任何成員,都不再影響已經(jīng)實(shí)例化的對象了。此時(shí),對象具有了和屬性,同時(shí)具有了構(gòu)造函數(shù)的原型對象的所有成員,當(dāng)然,此時(shí)該原型對象是沒有成員的。 學(xué)到原型的時(shí)候感覺頭都大了/(ㄒoㄒ)/~~ 尤其是prototype和__proto__ 傻傻分不清,通過多番查找資料,根據(jù)自己的理解,記錄下最近研究對象的一些心得,做一個(gè)記錄與總...
摘要:忍者級(jí)別的函數(shù)操作對于什么是匿名函數(shù),這里就不做過多介紹了。我們需要知道的是,對于而言,匿名函數(shù)是一個(gè)很重要且具有邏輯性的特性。通常,匿名函數(shù)的使用情況是創(chuàng)建一個(gè)供以后使用的函數(shù)。 JS 中的遞歸 遞歸, 遞歸基礎(chǔ), 斐波那契數(shù)列, 使用遞歸方式深拷貝, 自定義事件添加 這一次,徹底弄懂 JavaScript 執(zhí)行機(jī)制 本文的目的就是要保證你徹底弄懂javascript的執(zhí)行機(jī)制,如果...
摘要:原型鏈?zhǔn)紫龋膶ο笃胀▽ο蠛秃瘮?shù)對象都會(huì)有屬性,指向創(chuàng)建它的構(gòu)造函數(shù)的原型對象,比如上面的例子這就形成了原型鏈,會(huì)一直查找原型對象的屬性,直到為。,保證原型鏈能夠正常結(jié)束。 前言 一般談到j(luò)s中的繼承的時(shí)候,一定會(huì)遇到原型,原型鏈的問題,原型里面又有prototype,__proto__,constructor屬性,講到這兒,很多同學(xué)是不是都一頭霧水,傻傻分不清楚,因?yàn)楣ぷ髦杏玫降牡胤?..
摘要:組合方式繼承終極版工商建設(shè)開心能分清是孩子還是父輩二狗的構(gòu)造函數(shù)已指向圖示關(guān)鍵代碼創(chuàng)建對象的方法就是用原型鏈來連接的。也讓二狗有了確定的歸屬。 一、繼承原理 原型鏈不知道什么是原型鏈?來讀幾個(gè)關(guān)鍵詞: 哥歐 構(gòu) 構(gòu)造函數(shù) 構(gòu)造函數(shù) 構(gòu)造函數(shù) 實(shí)例 實(shí)例 實(shí)例 原型對象 原型對象 原型對象 prototype prototype prototype __proto__ __pro...
閱讀 1123·2021-11-08 13:13
閱讀 1707·2019-08-30 15:55
閱讀 2762·2019-08-29 11:26
閱讀 2427·2019-08-26 13:56
閱讀 2549·2019-08-26 12:15
閱讀 2125·2019-08-26 11:41
閱讀 1394·2019-08-26 11:00
閱讀 1530·2019-08-23 18:30