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

資訊專(zhuān)欄INFORMATION COLUMN

JS原型鏈

neuSnail / 3409人閱讀

摘要:構(gòu)造函數(shù)除了以指定模式創(chuàng)建對(duì)象之外,構(gòu)造函數(shù)也做了另一個(gè)有用的事情它自動(dòng)地為新創(chuàng)建的對(duì)象設(shè)置一個(gè)原型對(duì)象。正式來(lái)說(shuō),如果思考一下分類(lèi)的概念并且我們已經(jīng)對(duì)進(jìn)行了分類(lèi),那么構(gòu)造函數(shù)和原型對(duì)象合在一起可以叫作類(lèi)。

這篇文章是「深入ECMA-262-3」系列的一個(gè)概覽和摘要。每個(gè)部分都包含了對(duì)應(yīng)章節(jié)的鏈接,所以你可以閱讀它們以便對(duì)其有更深的理解。

對(duì)象

ECMAScript做為一個(gè)高度抽象的面向?qū)ο笳Z(yǔ)言,是通過(guò)對(duì)象來(lái)交互的。即使ECMAScript里邊也有基本類(lèi)型,但是,當(dāng)需要的時(shí)候,它們也會(huì)被轉(zhuǎn)換成對(duì)象。

一個(gè)對(duì)象就是一個(gè)屬性集合,并擁有一個(gè)獨(dú)立的prototype(原型)對(duì)象。這個(gè)prototype可以是一個(gè)對(duì)象或者null。

讓我們看一個(gè)關(guān)于對(duì)象的基本例子。一個(gè)對(duì)象的prototype是以內(nèi)部的[[Prototype]]屬性來(lái)引用的。但是,在示意圖里邊我們將會(huì)使用____下劃線標(biāo)記來(lái)替代兩個(gè)括號(hào),對(duì)于prototype對(duì)象來(lái)說(shuō)是:__proto__。

對(duì)于以下代碼:

var foo = {
  x: 10,
  y: 20
};

我們擁有一個(gè)這樣的結(jié)構(gòu),兩個(gè)明顯的自身屬性和一個(gè)隱含的__proto__屬性,這個(gè)屬性是對(duì)foo原型對(duì)象的引用:


這些prototype有什么用?讓我們以原型鏈(prototype chain)的概念來(lái)回答這個(gè)問(wèn)題。

原型鏈

原型對(duì)象也是簡(jiǎn)單的對(duì)象并且可以擁有它們自己的原型。如果一個(gè)原型對(duì)象的原型是一個(gè)非null的引用,那么以此類(lèi)推,這就叫作原型鏈。

原型鏈?zhǔn)且粋€(gè)用來(lái)實(shí)現(xiàn)繼承和共享屬性的有限對(duì)象鏈。

考慮這么一個(gè)情況,我們擁有兩個(gè)對(duì)象,它們之間只有一小部分不同,其他部分都相同。顯然,對(duì)于一個(gè)設(shè)計(jì)良好的系統(tǒng),我們將會(huì)重用相似的功能/代碼,而不是在每個(gè)多帶帶的對(duì)象中重復(fù)它。在基于類(lèi)的系統(tǒng)中,這個(gè)代碼重用風(fēng)格叫作類(lèi)繼承-你把相似的功能放入類(lèi)A中,然后類(lèi)B和類(lèi)C繼承類(lèi)A,并且擁有它們自己的一些小的額外變動(dòng)。

ECMAScript中沒(méi)有類(lèi)的概念。但是,代碼重用的風(fēng)格并沒(méi)有太多不同(盡管從某些方面來(lái)說(shuō)比基于類(lèi)(class-based)的方式要更加靈活)并且通過(guò)原型鏈來(lái)實(shí)現(xiàn)。這種繼承方式叫作委托繼承(delegation based inheritance)(或者,更貼近ECMAScript一些,叫作原型繼承(prototype based inheritance))。

跟例子中的類(lèi)A,BC相似,在ECMAScript中你創(chuàng)建對(duì)象:a,b,c。于是,對(duì)象a中存儲(chǔ)對(duì)象b和c中通用的部分。然后b和c只存儲(chǔ)它們自身的額外屬性或者方法。

var a = {
      x: 10,
    calculate: function (z) {
        return this.x + this.y + z
      }
};

var b = {
  y: 20,
  __proto__: a
};

var c = {
  y: 30,
  __proto__: a
};

// call the inherited method
b.calculate(30); // 60
c.calculate(40); // 80

足夠簡(jiǎn)單,是不是?我們看到bc訪問(wèn)到了在對(duì)象a中定義的calculate方法。這是通過(guò)原型鏈實(shí)現(xiàn)的。

規(guī)則很簡(jiǎn)單:如果一個(gè)屬性或者一個(gè)方法在對(duì)象自身中無(wú)法找到(也就是對(duì)象自身沒(méi)有一個(gè)那樣的屬性),然后它會(huì)嘗試在原型鏈中尋找這個(gè)屬性/方法。如果這個(gè)屬性在原型中沒(méi)有查找到,那么將會(huì)查找這個(gè)原型的原型,以此類(lèi)推,遍歷整個(gè)原型鏈(當(dāng)然這在類(lèi)繼承中也是一樣的,當(dāng)解析一個(gè)繼承的方法的時(shí)候-我們遍歷class鏈( class chain))。第一個(gè)被查找到的同名屬性/方法會(huì)被使用。因此,一個(gè)被查找到的屬性叫作繼承屬性。如果在遍歷了整個(gè)原型鏈之后還是沒(méi)有查找到這個(gè)屬性的話,返回undefined值。

注意,繼承方法中所使用的this的值被設(shè)置為原始對(duì)象,而并不是在其中查找到這個(gè)方法的(原型)對(duì)象。也就是,在上面的例子中this.y取的是b和c中的值,而不是a中的值。但是,this.x是取的是a中的值,并且又一次通過(guò)原型鏈機(jī)制完成。

如果沒(méi)有明確為一個(gè)對(duì)象指定原型,那么它將會(huì)使用__proto__的默認(rèn)值-Object.prototype。Object.prototype對(duì)象自身也有一個(gè)__proto__屬性,這是原型鏈的終點(diǎn)并且值為null。

下一張圖展示了對(duì)象a,b,c之間的繼承層級(jí):

注意: ES5標(biāo)準(zhǔn)化了一個(gè)實(shí)現(xiàn)原型繼承的可選方法,即使用 Object.create 函數(shù):

var b = Object.create(a, {y: {value: 20}});
var c = Object.create(a, {y: {value: 30}});

你可以在對(duì)應(yīng)的章節(jié)獲取到更多關(guān)于ES5新API的信息。 ES6標(biāo)準(zhǔn)化了 __proto__屬性,并且可以在對(duì)象初始化的時(shí)候使用它。

通常情況下需要對(duì)象擁有相同或者相似的狀態(tài)結(jié)構(gòu)(也就是相同的屬性集合),賦以不同的狀態(tài)值。在這個(gè)情況下我們可能需要使用構(gòu)造函數(shù)(constructor function),其以指定的模式來(lái)創(chuàng)造對(duì)象。

構(gòu)造函數(shù)

除了以指定模式創(chuàng)建對(duì)象之外,構(gòu)造函數(shù)也做了另一個(gè)有用的事情-它自動(dòng)地為新創(chuàng)建的對(duì)象設(shè)置一個(gè)原型對(duì)象。這個(gè)原型對(duì)象存儲(chǔ)在ConstructorFunction.prototype 屬性中。

換句話說(shuō),我們可以使用構(gòu)造函數(shù)來(lái)重寫(xiě)上一個(gè)擁有對(duì)象b和對(duì)象c的例子。因此,對(duì)象a(一個(gè)原型對(duì)象)的角色由Foo.prototype來(lái)扮演:

// a constructor function
function Foo(y) {
  // which may create objects
  // by specified pattern: they have after
  // creation own "y" property
  this.y = y;
}

// also "Foo.prototype" stores reference
// to the prototype of newly created objects,
// so we may use it to define shared/inherited
// properties or methods, so the same as in
// previous example we have:

// inherited property "x"
Foo.prototype.x = 10;

// and inherited method "calculate"
Foo.prototype.calculate = function (z) {
  return this.x + this.y + z;
};

// now create our "b" and "c"
// objects using "pattern" Foo
var b = new Foo(20);
var c = new Foo(30);

// call the inherited method
b.calculate(30); // 60
c.calculate(40); // 80

// let"s show that we reference
// properties we expect

console.log(

  b.__proto__ === Foo.prototype, // true
  c.__proto__ === Foo.prototype, // true

  // also "Foo.prototype" automatically creates
  // a special property "constructor", which is a
  // reference to the constructor function itself;
  // instances "b" and "c" may found it via
  // delegation and use to check their constructor

  b.constructor === Foo, // true
  c.constructor === Foo, // true
  Foo.prototype.constructor === Foo // true

  b.calculate === b.__proto__.calculate, // true
  b.__proto__.calculate === Foo.prototype.calculate // true

);

這個(gè)代碼可以表示為如下關(guān)系:

這張圖又一次說(shuō)明了每個(gè)對(duì)象都有一個(gè)原型。構(gòu)造函數(shù)Foo也有自己的__proto__,值為Function.prototype,Function.prototype也通過(guò)其__proto__屬性關(guān)聯(lián)到Object.prototype。因此,重申一下,Foo.prototype就是Foo的一個(gè)明確的屬性,指向?qū)ο?strong>b和對(duì)象c的原型。

正式來(lái)說(shuō),如果思考一下分類(lèi)的概念(并且我們已經(jīng)對(duì)Foo進(jìn)行了分類(lèi)),那么構(gòu)造函數(shù)和原型對(duì)象合在一起可以叫作「類(lèi)」。實(shí)際上,舉個(gè)例子,Python的第一級(jí)(first-class)動(dòng)態(tài)類(lèi)(dynamic classes)顯然是以同樣的屬性/方法處理方案來(lái)實(shí)現(xiàn)的。從這個(gè)角度來(lái)說(shuō),Python中的類(lèi)就是ECMAScript使用的委托繼承的一個(gè)語(yǔ)法糖。

注意: 在ES6中「類(lèi)」的概念被標(biāo)準(zhǔn)化了,并且實(shí)際上以一種構(gòu)建在構(gòu)造函數(shù)上面的語(yǔ)法糖來(lái)實(shí)現(xiàn),就像上面描述的一樣。從這個(gè)角度來(lái)看原型鏈成為了類(lèi)繼承的一種具體實(shí)現(xiàn)方式:

// ES6
class Foo {
  constructor(name) {
    this._name = name;
  }

  getName() {
    return this._name;
  }
}

class Bar extends Foo {
  getName() {
    return super.getName() + " Doe";
  }
}

var bar = new Bar("John");
console.log(bar.getName()); // John Doe

轉(zhuǎn)自 JavaScript. The core.

全面的課程內(nèi)容,只為打造企業(yè)最需要的WEB前端工程師, 最新前端視頻分享,請(qǐng)關(guān)注微信公眾號(hào)“一起玩前端”或掃描二維碼關(guān)注。

回復(fù)以下內(nèi)容,即可獲取對(duì)應(yīng)最新視頻。

001------ HTML

002------ CSS

003------ DIV+CSS

004------ HTML5

005------ CSS3

006------ Web響應(yīng)式布局

007------JavaScript視頻教程

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

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

相關(guān)文章

  • JS基礎(chǔ)-原型、原型真的不能一知半解

    摘要:原型鏈和對(duì)象的原型是對(duì)象實(shí)例和它的構(gòu)造函數(shù)之間建立的鏈接,它的值是構(gòu)造函數(shù)的。對(duì)象的原型根據(jù)上文提到的構(gòu)造調(diào)用函數(shù)的時(shí)候會(huì)創(chuàng)建一個(gè)新對(duì)象,自動(dòng)將的原型指向構(gòu)造函數(shù)的對(duì)象。 showImg(https://segmentfault.com/img/remote/1460000020185197); JS的原型、原型鏈一直是比較難理解的內(nèi)容,不少初學(xué)者甚至有一定經(jīng)驗(yàn)的老鳥(niǎo)都不一定能完全說(shuō)清...

    changfeng1050 評(píng)論0 收藏0
  • 從實(shí)現(xiàn)角度分析js原型

    摘要:從實(shí)現(xiàn)角度分析原型鏈歡迎來(lái)我的博客閱讀從實(shí)現(xiàn)角度分析原型鏈網(wǎng)上介紹原型鏈的優(yōu)質(zhì)文章已經(jīng)有很多了,比如說(shuō)作為補(bǔ)充,就讓我們換個(gè)角度,從實(shí)現(xiàn)來(lái)分析一下吧本文假設(shè)你對(duì)原型鏈已經(jīng)有所了解。 從實(shí)現(xiàn)角度分析js原型鏈 歡迎來(lái)我的博客閱讀:《從實(shí)現(xiàn)角度分析js原型鏈》 網(wǎng)上介紹原型鏈的優(yōu)質(zhì)文章已經(jīng)有很多了,比如說(shuō): https://github.com/mqyqingfeng/Blog/issu...

    CompileYouth 評(píng)論0 收藏0
  • 理解js原型與繼承

    摘要:相當(dāng)于在用原型繼承編寫(xiě)復(fù)雜代碼前理解原型繼承模型十分重要。同時(shí),還要清楚代碼中原型鏈的長(zhǎng)度,并在必要時(shí)結(jié)束原型鏈,以避免可能存在的性能問(wèn)題。 js是一門(mén)動(dòng)態(tài)語(yǔ)言,js沒(méi)有類(lèi)的概念,ES6 新增了class 關(guān)鍵字,但只是語(yǔ)法糖,JavaScript 仍舊是基于原型。 至于繼承,js的繼承與java這種傳統(tǒng)的繼承不一樣.js是基于原型鏈的繼承. 在javascript里面,每個(gè)對(duì)象都有一...

    wthee 評(píng)論0 收藏0
  • js原型 原型 原型的繼承

    摘要:圖片描述缺點(diǎn)是無(wú)法實(shí)現(xiàn)多繼承可以在構(gòu)造函數(shù)中,為實(shí)例添加實(shí)例屬性。 對(duì)象的方法 Object.assign() 對(duì)象可以簡(jiǎn)寫(xiě) ,如果 key 和 value 相等則可以簡(jiǎn)寫(xiě) let name = xm; let age = 2; let obj = { name, age, fn(){ // 可以省略函數(shù)關(guān)鍵字和冒號(hào): console.log(2...

    soasme 評(píng)論0 收藏0
  • js原型

    摘要:構(gòu)造函數(shù),實(shí)例,原型三者的關(guān)系如下圖構(gòu)造函數(shù)是構(gòu)成整個(gè)原型鏈的關(guān)鍵,是他利用將原型傳給了后代。因此,通過(guò)操縱構(gòu)造函數(shù)的,就能夠操縱原型鏈,從而對(duì)原型鏈進(jìn)行自在的拼接。 要理解js的原型鏈主要就是理清楚以下三者的關(guān)系: 構(gòu)造函數(shù)的protitype屬性 對(duì)象的__proto__屬性 對(duì)象的constructor屬性 在js中,函數(shù)作為一等公民,它是一個(gè)對(duì)象,可以擁有自己的屬性,可...

    NervosNetwork 評(píng)論0 收藏0
  • 【前端基礎(chǔ)進(jìn)階】JS原型原型、對(duì)象詳解

    摘要:二構(gòu)造函數(shù)我們先復(fù)習(xí)一下構(gòu)造函數(shù)的知識(shí)上面的例子中和都是的實(shí)例。這兩個(gè)實(shí)例都有一個(gè)構(gòu)造函數(shù)屬性,該屬性是一個(gè)指針指向。原型鏈其中是對(duì)象的實(shí)例。 一. 普通對(duì)象與函數(shù)對(duì)象 JavaScript 中,萬(wàn)物皆對(duì)象!但對(duì)象也是有區(qū)別的。分為普通對(duì)象和函數(shù)對(duì)象,Object 、Function 是 JS 自帶的函數(shù)對(duì)象。下面舉例說(shuō)明 var o1 = {}; var o2 =new Objec...

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

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

0條評(píng)論

閱讀需要支付1元查看
<