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

資訊專欄INFORMATION COLUMN

談一談原型和原型鏈

546669204 / 2750人閱讀

摘要:相關(guān)名詞概念原型的所有對(duì)象中都包含了一個(gè)內(nèi)部屬性,這個(gè)屬性所對(duì)應(yīng)的就是該對(duì)象的原型的函數(shù)對(duì)象,除了原型之外,還預(yù)置了屬性當(dāng)函數(shù)對(duì)象作為構(gòu)造函數(shù)創(chuàng)建實(shí)例時(shí),該屬性值將被作為實(shí)例對(duì)象的原型。

1 寫在前面

JavaScript中除了基本類型外的數(shù)據(jù)類型,都是對(duì)象。但是由于其沒有 類(class,ES6引入了class,但只是語法糖)的概念,如何將所有對(duì)象聯(lián)系起來就成了一個(gè)問題,于是就有了原型和原型鏈的概念。

2 為什么會(huì)有原型和原型鏈


1994年,網(wǎng)景公司(Netscape)發(fā)布了Navigator瀏覽器0.9版,但是剛開始的Js沒有繼承機(jī)制,更別提像同時(shí)期興盛的C++和Java這樣擁有面向?qū)ο蟮母拍?。在?shí)際的開發(fā)過程中,工程師們發(fā)現(xiàn)沒有繼承機(jī)制很難解決一些問題,必須有一種機(jī)制能將所有的對(duì)象關(guān)聯(lián)起來。Brendan Eich鑒于以上情況,但不想把Js設(shè)計(jì)得過為復(fù)雜,于是引入了new關(guān)鍵詞和constructor構(gòu)造函數(shù)來簡(jiǎn)化對(duì)象的設(shè)計(jì),引入了prototype函數(shù)對(duì)象來包含所有實(shí)例對(duì)象的構(gòu)造函數(shù)的屬性和方法,引入了proto和原型鏈的概念解決繼承的問題。

3 相關(guān)名詞概念 原型

JavaScript的所有對(duì)象中都包含了一個(gè) [proto] 內(nèi)部屬性,這個(gè)屬性所對(duì)應(yīng)的就是該對(duì)象的原型

JavaScript的函數(shù)對(duì)象,除了原型 [proto] 之外,還預(yù)置了 prototype 屬性

當(dāng)函數(shù)對(duì)象作為構(gòu)造函數(shù)創(chuàng)建實(shí)例時(shí),該 prototype 屬性值將被作為實(shí)例對(duì)象的原型 [proto]。

原型鏈

當(dāng)一個(gè)對(duì)象調(diào)用的屬性/方法自身不存在時(shí),就會(huì)去自己 [proto] 關(guān)聯(lián)的前輩 prototype 對(duì)象上去找

如果沒找到,就會(huì)去該 prototype 原型 [proto] 關(guān)聯(lián)的前輩 prototype 去找。依次類推,直到找到屬性/方法或 undefined 為止。從而形成了所謂的“原型鏈”

也就是說

JavaScript中的對(duì)象,都有一個(gè)內(nèi)置屬性[[Prototype]],指向這個(gè)對(duì)象的原型對(duì)象。當(dāng)查找一個(gè)屬性或方法時(shí),如果在當(dāng)前對(duì)象中找不到定義,會(huì)繼續(xù)在當(dāng)前對(duì)象的原型對(duì)象中查找;如果原型對(duì)象中依然沒有找到,會(huì)繼續(xù)在原型對(duì)象的原型中查找(原型也是對(duì)象,也有它自己的原型);如此繼續(xù),直到找到為止,或者查找到最頂層的原型對(duì)象中也沒有找到,就結(jié)束查找,返回undefined??梢钥闯?,這個(gè)查找過程是一個(gè)鏈?zhǔn)降牟檎?,每個(gè)對(duì)象都有一個(gè)到它自身原型對(duì)象的鏈接,這些鏈接組件的整個(gè)鏈條就是原型鏈。擁有相同原型的多個(gè)對(duì)象,他們的共同特征正是通過這種查找模式體現(xiàn)出來的。
在上面的查找過程,我們提到了最頂層的原型對(duì)象,這個(gè)對(duì)象就是Object.prototype,這個(gè)對(duì)象中保存了最常用的方法,如toString、valueOf、hasOwnProperty等,因此我們才能在任何對(duì)象中使用這些方法。

4 創(chuàng)建對(duì)象的方式 1、字面量方式

當(dāng)通過字面量方式創(chuàng)建對(duì)象時(shí),它的原型就是Object.prototype。雖然我們無法直接訪問內(nèi)置屬性[[Prototype]],但我們可以通過Object.getPrototypeOf()或?qū)ο蟮腳_proto__獲取對(duì)象的原型。

var obj = {};
Object.getPrototypeOf(obj) === Object.prototype;   // true
obj.__proto__  === Object.prototype;            // true
2、構(gòu)造函數(shù)的調(diào)用

通過函數(shù)的構(gòu)造調(diào)用(注意,我們不把它叫做構(gòu)造函數(shù),因?yàn)镴avaScript中同樣沒有構(gòu)造函數(shù)的概念,所有的函數(shù)都是平等的,只不過用來創(chuàng)建對(duì)象時(shí),函數(shù)的調(diào)用方式不同而已)也是一種常用的創(chuàng)建對(duì)象的方式?;谕粋€(gè)函數(shù)創(chuàng)建出來的對(duì)象,理應(yīng)可以共享一些相同的屬性或方法,但這些屬性或方法如果放在Object.prototype里,那么所有的對(duì)象都可以使用它們了,作用域太大,顯然不合適。于是,JavaScript在定義一個(gè)函數(shù)時(shí),同時(shí)為這個(gè)函數(shù)定義了一個(gè) 默認(rèn)的prototype屬性,所有共享的屬性或方法,都放到這個(gè)屬性所指向的對(duì)象中。由此看出,通過一個(gè)函數(shù)的構(gòu)造調(diào)用創(chuàng)建的對(duì)象,它的原型就是這個(gè)函數(shù)的prototype指向的對(duì)象。

var f = function(name) { this.name = name };
f.prototype.getName = function() { return this.name; }   //在prototype下存放所有對(duì)象的共享方法
var obj = new f("JavaScript");
obj.getName();                  // JavaScript
obj.__proto__ === f.prototype;  // true
3、Object.create()

第三種常用的創(chuàng)建對(duì)象的方式是使用Object.create()。這個(gè)方法會(huì)以你傳入的對(duì)象作為創(chuàng)建出來的對(duì)象的原型。

var obj = {};
var obj2 = Object.create(obj);
obj2.__proto__ === obj;       // true

這種方式還可以模擬對(duì)象的“繼承”行為。

function Foo(name) {
    this.name = name;
}

Foo.prototype.myName = function() {
    return this.name;
};

function Bar(name,label) {
    Foo.call( this, name );   //
    this.label = label;
}

// temp對(duì)象的原型是Foo.prototype
var temp = Object.create( Foo.prototype );  

// 通過new Bar() 創(chuàng)建的對(duì)象,其原型是temp, 而temp的原型是Foo.prototype,
// 從而兩個(gè)原型對(duì)象Bar.prototype和Foo.prototype 有了"繼承"關(guān)系
Bar.prototype = temp;

Bar.prototype.myLabel = function() {
    return this.label;
};

var a = new Bar( "a", "obj a" );

a.myName(); // "a"
a.myLabel(); // "obj a"
a.__proto__.__proto__ === Foo.prototype;  //true
5 __proto__和prototype

這是容易混淆的兩個(gè)屬性。__proto__指向當(dāng)前對(duì)象的原型,prototype是函數(shù)才具有的屬性,默認(rèn)情況下,new 一個(gè)函數(shù)創(chuàng)建出的對(duì)象,其原型都指向這個(gè)函數(shù)的prototype屬性。

每個(gè)實(shí)例對(duì)象(object )都有一個(gè)私有屬性(稱之為 __proto__)指向它的原型對(duì)象(prototype)。該原型對(duì)象也有一個(gè)自己的原型對(duì)象 ,層層向上直到一個(gè)對(duì)象的原型對(duì)象為 null。根據(jù)定義,null 沒有原型,并作為這個(gè)原型鏈中的最后一個(gè)環(huán)節(jié)。

6 Javascript如何實(shí)現(xiàn)繼承?

1.構(gòu)造函數(shù)綁定:使用 call 或 apply 方法,將父對(duì)象的構(gòu)造函數(shù)綁定在子對(duì)象上

function Cat(name,color){
  Animal.apply(this, arguments);
  this.name = name;
  this.color = color;
}

實(shí)例繼承:將子對(duì)象的 prototype 指向父對(duì)象的一個(gè)實(shí)例

Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;

拷貝繼承:如果把父對(duì)象的所有屬性和方法,拷貝進(jìn)子對(duì)象

    function extend(Child, Parent) {
     var p = Parent.prototype;
     var c = Child.prototype;
     for (var i in p) {
        c[i] = p[i];
     }
     c.uber = p;
    }

原型繼承:將子對(duì)象的 prototype 指向父對(duì)象的 prototype

 function extend(Child, Parent) {
        var F = function(){};
       F.prototype = Parent.prototype;
       Child.prototype = new F();
       Child.prototype.constructor = Child;
       Child.uber = Parent.prototype;
    }

ES6 語法糖 extends:class ColorPoint extends Point {}

   class ColorPoint extends Point {
       constructor(x, y, color) {
          super(x, y); // 調(diào)用父類的constructor(x, y)
          this.color = color;
       }
       toString() {
          return this.color + " " + super.toString(); // 調(diào)用父類的toString()
       }
    }

如有侵權(quán),請(qǐng)聯(lián)系刪除

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

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

相關(guān)文章

  • 一談javascript面向?qū)ο?/b>

    摘要:從今天起我們開始討論的面向?qū)ο竺嫦驅(qū)ο蟾拍罾斫饷嫦驅(qū)ο笳Z言有個(gè)標(biāo)志它們都具有類的概念,通過類可以創(chuàng)建任意多個(gè)具有相同屬性和方法的對(duì)象。 從今天起我們開始討論javascript的面向?qū)ο?面向?qū)ο蟾拍罾斫?面向?qū)ο笳Z言有個(gè)標(biāo)志=>它們都具有類的概念,通過類可以創(chuàng)建任意多個(gè)具有相同屬性和方法的對(duì)象。面向?qū)ο笥腥筇匦? 封裝 繼承 多態(tài) 但JS中對(duì)象與純面向?qū)ο笳Z言中的對(duì)象是不同的 J...

    PiscesYE 評(píng)論0 收藏0
  • 初學(xué)者快速學(xué)會(huì)javascript原型,原型原型繼承

    摘要:學(xué)習(xí),總繞不開原型,原型鏈,繼承等等這些知識(shí)。對(duì)象那么好,怎么才能找一個(gè)呸,其實(shí)是創(chuàng)建創(chuàng)建對(duì)象的方法對(duì)象字面量工廠模式構(gòu)造函數(shù)模式原型模式等。原型鏈有什么用來談?wù)劺^承,繼承可以利用構(gòu)造函數(shù),使用屬性等來實(shí)現(xiàn)。 初學(xué)者學(xué)習(xí)javascript可能會(huì)感覺很困擾,但是你一旦真正了解了它,我相信你會(huì)愛上它。學(xué)習(xí)ECMAScript,總繞不開原型,原型鏈,繼承等等這些知識(shí)。今天把它們放在一塊兒,...

    hiYoHoo 評(píng)論0 收藏0
  • javascript面向?qū)ο笾岸鄳B(tài)”

    摘要:之前,本質(zhì)上不能算是一門面向?qū)ο蟮木幊陶Z言,因?yàn)樗鼘?duì)于封裝繼承多態(tài)這些面向?qū)ο笳Z言的特點(diǎn)并沒有在語言層面上提供原生的支持。所以在中出現(xiàn)了等關(guān)鍵字,解決了面向?qū)ο笾谐霈F(xiàn)了問題。 ES6之前,javascript本質(zhì)上不能算是一門面向?qū)ο蟮木幊陶Z言,因?yàn)樗鼘?duì)于封裝、繼承、多態(tài)這些面向?qū)ο笳Z言的特點(diǎn)并沒有在語言層面上提供原生的支持。但是,它引入了原型(prototype)的概念,可以讓我們以...

    JerryWangSAP 評(píng)論0 收藏0
  • JS程序

    摘要:設(shè)計(jì)模式是以面向?qū)ο缶幊虨榛A(chǔ)的,的面向?qū)ο缶幊毯蛡鹘y(tǒng)的的面向?qū)ο缶幊逃行┎顒e,這讓我一開始接觸的時(shí)候感到十分痛苦,但是這只能靠自己慢慢積累慢慢思考。想繼續(xù)了解設(shè)計(jì)模式必須要先搞懂面向?qū)ο缶幊?,否則只會(huì)讓你自己更痛苦。 JavaScript 中的構(gòu)造函數(shù) 學(xué)習(xí)總結(jié)。知識(shí)只有分享才有存在的意義。 是時(shí)候替換你的 for 循環(huán)大法了~ 《小分享》JavaScript中數(shù)組的那些迭代方法~ ...

    melody_lql 評(píng)論0 收藏0
  • 淺談JavaScript面向?qū)ο?/b>

    摘要:不必在構(gòu)造函數(shù)中定義對(duì)象實(shí)例的信息。其次,按照一切事物皆對(duì)象的這餓極本的面向?qū)ο蟮姆▌t來說,類本身并不是一個(gè)對(duì)象,然而原型方式的構(gòu)造函數(shù)和原型本身也是個(gè)對(duì)象。第二個(gè)問題就是在創(chuàng)建子類型的實(shí)例時(shí),不能向超類型的構(gòu)造函數(shù)中傳遞參數(shù)。 前言 對(duì)象(Object)應(yīng)該算是js中最為重要的部分,也是js中非常難懂晦澀的一部分。更是面試以及框架設(shè)計(jì)中各出沒。寫這篇文章,主要參考與JavaScrip...

    cyixlq 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<