成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

傻傻分不清的__proto__與prototype

YancyYe / 403人閱讀

摘要:今天同事小英童鞋問了我一個問題小英童鞋認(rèn)為的原型對象是,所以會繼承的屬性,調(diào)用相當(dāng)于調(diào)用,但結(jié)果不是一個方法。構(gòu)造函數(shù)創(chuàng)建對象實例函數(shù)有兩個不同的內(nèi)部方法和。如果不通過關(guān)鍵字調(diào)用函數(shù),則執(zhí)行函數(shù),從而直接執(zhí)行代碼中的函數(shù)體。

今天同事小英童鞋問了我一個問題:

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會繼承Foo.prototype的屬性,調(diào)用Foo.combineName()相當(dāng)于調(diào)用Foo.prototype.combineName(),但結(jié)果Foo.combineName()不是一個方法。

會造成這個問題的原因一定是因為小英童鞋弄混了原型和繼承的一些原理,下面我們來整理一下原型和繼承的相關(guān)原理,找出問題的根本原因。

prototype

prototype是一個擁有 [[Construct]] 內(nèi)部方法的對象才有的屬性。

例如函數(shù),對象的方法,ES6 中的類。注意 ES6 中的箭頭函數(shù)沒有 [[Construct]] 方法,因此沒有prototype這個屬性,除非你為它添加一個。

當(dāng)創(chuàng)建函數(shù)時,JavaScript 會為這個函數(shù)自動添加prototype屬性,這個屬性指向的是一個原型對象Functionname.prototype。我們可以向這個原型對象添加屬性或?qū)ο?,甚至可以指向一個現(xiàn)有的對象。

__proto__

接下來我們說說繼承,每個對象都有一個__proto__屬性,這個屬性是用來標(biāo)識自己所繼承的原型。

注意: JavaScript 中任意對象都有一個內(nèi)置屬性 [[Prototype]] ,在ES5之前沒有標(biāo)準(zhǔn)的方法訪問這個內(nèi)置屬性,但是大多數(shù)瀏覽器都支持通過__proto__來訪問。以下統(tǒng)一使用__proto__來訪問 [[Prototype]],在實際開發(fā)中是不能這樣訪問的。

原型鏈

JavaScript 可以通過prototype__proto__在兩個對象之間創(chuàng)建一個關(guān)聯(lián),使得一個對象就可以通過委托訪問另一個對象的屬性和函數(shù)。

這樣的一個關(guān)聯(lián)就是原型鏈,一個由對象組成的有限對象鏈,用于實現(xiàn)繼承和共享屬性。

構(gòu)造函數(shù)創(chuàng)建對象實例

JavaScript 函數(shù)有兩個不同的內(nèi)部方法:[[Call]][[Construct]] 。

如果不通過new關(guān)鍵字調(diào)用函數(shù),則執(zhí)行 [[Call]] 函數(shù),從而直接執(zhí)行代碼中的函數(shù)體。

當(dāng)通過new關(guān)鍵字調(diào)用函數(shù)時,執(zhí)行的是 [[Construct]] 函數(shù),它負(fù)責(zé)創(chuàng)建一個實例對象,把實例對象的__proto__屬性指向構(gòu)造函數(shù)的prototype來實現(xiàn)繼承構(gòu)造函數(shù)prototype的所有屬性和方法,將this綁定到實例上,然后再執(zhí)行函數(shù)體。

模擬一個構(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)建對象實例時這兩個屬性的指向,以下使用一張圖來總結(jié)一下如何通過prototype__proto__實現(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上的屬性和方法。而實例foo的原型鏈上有Foo.prototype,因此foo可以繼承Foo.prototype上的屬性和方法。

到這里,我們可以很簡單的解答小英童鞋的問題了,在Foo的原型鏈上沒有Foo.prototype,無法繼承Foo.prototype上的combineName方法,因此會拋出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)文章不易,若本文對你有幫助,請點贊、推薦和關(guān)注作者支持。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/92015.html

相關(guān)文章

  • 傻傻分不清的Manifest

    摘要:的英文含義是名單種技術(shù)的確都是把當(dāng)做清單使用緩存清單清單打包資源路徑清單打包清單只不過是在不同的場景中使用特定的清單來完成某些功能所以,學(xué)好英文是多么重要,這樣才不會傻傻分不清到底是干啥的 在前端,說到manifest,其實是有歧義的,就我了解的情況來說,manifest可以指代下列含義: html標(biāo)簽的manifest屬性: 離線緩存(目前已被廢棄) PWA: 將Web應(yīng)用程序...

    printempw 評論0 收藏0
  • __proto__prototype之區(qū)別和聯(lián)系

    摘要:當(dāng)這步完成,這個對象就與構(gòu)造函數(shù)再無聯(lián)系,這個時候即使構(gòu)造函數(shù)再加任何成員,都不再影響已經(jīng)實例化的對象了。此時,對象具有了和屬性,同時具有了構(gòu)造函數(shù)的原型對象的所有成員,當(dāng)然,此時該原型對象是沒有成員的。 學(xué)到原型的時候感覺頭都大了/(ㄒoㄒ)/~~ 尤其是prototype和__proto__ 傻傻分不清,通過多番查找資料,根據(jù)自己的理解,記錄下最近研究對象的一些心得,做一個記錄與總...

    paulli3 評論0 收藏0
  • JavasScript重難點知識

    摘要:忍者級別的函數(shù)操作對于什么是匿名函數(shù),這里就不做過多介紹了。我們需要知道的是,對于而言,匿名函數(shù)是一個很重要且具有邏輯性的特性。通常,匿名函數(shù)的使用情況是創(chuàng)建一個供以后使用的函數(shù)。 JS 中的遞歸 遞歸, 遞歸基礎(chǔ), 斐波那契數(shù)列, 使用遞歸方式深拷貝, 自定義事件添加 這一次,徹底弄懂 JavaScript 執(zhí)行機(jī)制 本文的目的就是要保證你徹底弄懂javascript的執(zhí)行機(jī)制,如果...

    forsigner 評論0 收藏0
  • js 原型鏈的那些事兒

    摘要:原型鏈?zhǔn)紫?,的對象普通對象和函?shù)對象都會有屬性,指向創(chuàng)建它的構(gòu)造函數(shù)的原型對象,比如上面的例子這就形成了原型鏈,會一直查找原型對象的屬性,直到為。,保證原型鏈能夠正常結(jié)束。 前言 一般談到j(luò)s中的繼承的時候,一定會遇到原型,原型鏈的問題,原型里面又有prototype,__proto__,constructor屬性,講到這兒,很多同學(xué)是不是都一頭霧水,傻傻分不清楚,因為工作中用到的地方...

    fuyi501 評論0 收藏0
  • JavaScript繼承的幾種方式

    摘要:組合方式繼承終極版工商建設(shè)開心能分清是孩子還是父輩二狗的構(gòu)造函數(shù)已指向圖示關(guān)鍵代碼創(chuàng)建對象的方法就是用原型鏈來連接的。也讓二狗有了確定的歸屬。 一、繼承原理 原型鏈不知道什么是原型鏈?來讀幾個關(guān)鍵詞: 哥歐 構(gòu) 構(gòu)造函數(shù) 構(gòu)造函數(shù) 構(gòu)造函數(shù) 實例 實例 實例 原型對象 原型對象 原型對象 prototype prototype prototype __proto__ __pro...

    SegmentFault 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<