亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

理解原型鏈和原型繼承

XboxYan / 2755人閱讀

摘要:原型鏈和構(gòu)造函數(shù)是一種面向?qū)ο蟮恼Z言,并且可以進(jìn)行原型繼承。來了極大的支持了工程化,它的標(biāo)準(zhǔn)讓瀏覽器內(nèi)部實(shí)現(xiàn)類和類的繼承構(gòu)造函數(shù)構(gòu)造函數(shù)調(diào)用父類構(gòu)造函數(shù)現(xiàn)在瀏覽器對(duì)其支持程度還不高。

原型鏈

原型鏈比作用域鏈要好理解的多。

JavaScript中的每個(gè)對(duì)象,都有一個(gè)內(nèi)置的_proto_屬性。這個(gè)屬性是編程不可見的(雖然ES6標(biāo)準(zhǔn)中開放了這個(gè)屬性,然而瀏覽器對(duì)這個(gè)屬性的可見性的支持不同),它實(shí)際上是對(duì)另一個(gè)對(duì)象或者null的引用。

當(dāng)一個(gè)對(duì)象需要引用一個(gè)屬性時(shí),JavaScript引擎首先會(huì)從這個(gè)對(duì)象自身的屬性表中尋找這個(gè)屬性標(biāo)識(shí),如果找到則進(jìn)行相應(yīng)讀寫操作,若沒有在自身的屬性表中找到,則在_proto_屬性引用的對(duì)象的屬性表中查找,如此往復(fù),直到找到這個(gè)屬性或者_proto_屬性指向null為止。

這個(gè)_proto_的引用鏈,被稱作原型鏈。

注意,此處有一個(gè)性能優(yōu)化的問題:往原型鏈越深處搜索,耗費(fèi)的時(shí)間越多。

原型鏈和構(gòu)造函數(shù)

JavaScript是一種面向?qū)ο蟮恼Z言,并且可以進(jìn)行原型繼承。

JavaScript中的函數(shù)有一個(gè)屬性prototype,這個(gè)prototype屬性是一個(gè)對(duì)象,它的一個(gè)屬性constructor引用該函數(shù)自身。即:

func.prototype.constructor === func; // ==> true  

這個(gè)屬性有什么用呢?我們知道一個(gè),一個(gè)函數(shù)使用new操作符調(diào)用時(shí),會(huì)作為構(gòu)造函數(shù)返回一個(gè)新的對(duì)象。這個(gè)對(duì)象的_proto_屬性引用其構(gòu)造函數(shù)的prototype屬性

因此這個(gè)就不難理解了:

var obj = new Func();

obj.constructor == Func; // ==> true

還有這個(gè):

obj instanceof Func; // ==> true  

也是通過查找原型鏈上的constructor屬性實(shí)現(xiàn)的。

構(gòu)造函數(shù)生成的不同實(shí)例的_proto_屬性是對(duì)同一個(gè)prototype對(duì)象的引用。所以修改prototype對(duì)象會(huì)影響所有的實(shí)例。

“子類”繼承實(shí)現(xiàn)的幾種方式

之所以子類要加引號(hào),是因?yàn)檫@里說“類”的概念是不嚴(yán)謹(jǐn)?shù)?。JavaScript是一門面向?qū)ο蟮恼Z言,但是它跟Java等語言不同,在ES6標(biāo)準(zhǔn)出爐之前,它是沒有類的定義的。

但是熟悉Java等語言的程序員,也希望使用JavaScript時(shí),跟使用Java相似,通過類生成實(shí)例,通過子類復(fù)用代碼。那么在ES6之前,怎么做到像如下代碼一樣使用類似"類"的方式呢?

var parent = new Parent("Sam");

var child = new Children("Samson");

parent.say(); // ==> "Hello, Sam!"

child.say(); // ==> "Hello, Samson! hoo~~"

child instanceof Parent; // ==> true 

我們看到,這里我們把構(gòu)造函數(shù)當(dāng)做類來用。

以下我們討論一下實(shí)現(xiàn)的幾種方式:

最簡(jiǎn)單的方式

結(jié)合原型鏈的概念,我們很容易就能寫出這樣的代碼:

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

Parent.prototype.say = function(){
    console.log("Hello, " + this.name + "!");
}

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

Children.prototype = new Parent();

Children.prototype.say = function(){
    console.log("Hello, " + this.name + "! hoo~~");
}

這個(gè)方式缺點(diǎn)很明顯:作為子類的構(gòu)造函數(shù)需要依賴一個(gè)父類的對(duì)象。這個(gè)對(duì)象中的屬性name根本毫無用處。

第一次改進(jìn)
// ...
Children.prototype = Parent.prototype;
// ...

這樣就不會(huì)產(chǎn)生無用的父類屬性了。

然而,這樣的話子類和父類的原型就引用了同一個(gè)對(duì)象,修改子類的prototype也會(huì)影響父類的原型。

這時(shí)候我們發(fā)現(xiàn):

parent.say(); // ==> "Hello,Sam! hoo~~"

這第一次改進(jìn)還不如不改。

第二次改進(jìn)——臨時(shí)構(gòu)造函數(shù)/Object.create
function F(){  // empty  
}

F.prototype = Parent.prototype;

Children.prototype = new F();

// ...

parent.say(); // ==> "Hello, Sam!"
child.say();  // ==> "Hello, Samson! hoo~~"

這樣一來,修改子類的原型只是修改了F的一個(gè)實(shí)例的屬性,并沒有改變Parent.prototype,從而解決了上面的問題。

在ES5的時(shí)代,我們還可以直接這樣:

Children.prototype = Object.create(Parent.prototype);

這里的思路是一樣的,都是讓子類的prototype不直接引用父類prototype。目前的現(xiàn)代瀏覽器幾乎已經(jīng)添加了對(duì)這個(gè)方法的支持。(但我們下面會(huì)仍以臨時(shí)構(gòu)造函數(shù)為基礎(chǔ))

但是細(xì)細(xì)思考,這個(gè)方案仍有需要優(yōu)化的地方。例如:如何讓父類的構(gòu)造函數(shù)邏輯直接運(yùn)用到子類中,而不是再重新寫一遍一樣的?這個(gè)例子中只有一個(gè)name屬性的初始化,那么假設(shè)有很多屬性且邏輯一樣的話,豈不是沒有做到代碼重用?

第三次改進(jìn)——構(gòu)造函數(shù)方法借用

使用apply,實(shí)現(xiàn)“方法重用”的思想。

function Children(name){
    Parent.apply(this, arguments);
    // do other initial things
}
“圣杯”模式

現(xiàn)在完整的代碼如下:

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

Parent.prototype.say = function(){
    console.log("Hello, " + this.name + "!");
}

function Children(name){
    Parent.apply(this, arguments);
    // do other initial things
}

function F(){  // empty  
}

F.prototype = Parent.prototype;

Child.prototype = new F();

Children.prototype.say = function(){
    console.log("Hello, " + this.name + "! hoo~~");
}

這就是所謂“圣杯”模式,聽著很高大上吧?

以上就是ES3的時(shí)代,我們用來實(shí)現(xiàn)原型繼承的一個(gè)近似最佳實(shí)踐。

“圣杯”模式的問題

“圣杯”模式依然存在一個(gè)問題:雖然父類和子類實(shí)例的繼承的prototype對(duì)象不是同一個(gè)實(shí)例,但是這兩個(gè)prototype對(duì)象上面的屬性引用了同樣的對(duì)象。

假設(shè)我們有:

Parent.prototype.a = { x: 1};
// ...

那么即使是“圣杯”模式下,依然會(huì)有這樣的問題:

parent.x // ==> 1
child.x  // ==> 1

child.x = 2;
parent.x // ==>2

問題在于,JavaScript的拷貝不是 深拷貝(deepclone)

要解決這個(gè)問題,我們可以利用屬性遞歸遍歷,自己實(shí)現(xiàn)一個(gè)深拷貝的方法。這個(gè)方法在這里我就不寫了。

ES6來了

ES6極大的支持了工程化,它的標(biāo)準(zhǔn)讓瀏覽器內(nèi)部實(shí)現(xiàn)類和類的繼承:

class Parent {
    constructor(name) { //構(gòu)造函數(shù)
          this.name = name;
    }
    say() {
          console.log("Hello, " + this.name + "!");
    }
}

class Children extends Parent {
    constructor(name) { //構(gòu)造函數(shù)
        super(name);    //調(diào)用父類構(gòu)造函數(shù)
        // ...
    }
    say() {
          console.log("Hello, " + this.name + "! hoo~~");
    }
}

現(xiàn)在瀏覽器對(duì)其支持程度還不高。但是這種寫法的確省力不少。讓我們對(duì)未來拭目以待。

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

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

相關(guān)文章

  • 詳解javascript的類

    摘要:原文地址詳解的類博主博客地址的個(gè)人博客從當(dāng)初的一個(gè)彈窗語言,一步步發(fā)展成為現(xiàn)在前后端通吃的龐然大物。那么,的類又該怎么定義呢在面向?qū)ο缶幊讨?,類是?duì)象的模板,定義了同一組對(duì)象又稱實(shí)例共有的屬性和方法。這個(gè)等同于的屬性現(xiàn)已棄用。。 前言 生活有度,人生添壽。 原文地址:詳解javascript的類 博主博客地址:Damonare的個(gè)人博客 ??Javascript從當(dāng)初的一個(gè)彈窗語言,一...

    hufeng 評(píng)論0 收藏0
  • 詳解javascript的類

    摘要:原文地址詳解的類博主博客地址的個(gè)人博客從當(dāng)初的一個(gè)彈窗語言,一步步發(fā)展成為現(xiàn)在前后端通吃的龐然大物。那么,的類又該怎么定義呢在面向?qū)ο缶幊讨?,類是?duì)象的模板,定義了同一組對(duì)象又稱實(shí)例共有的屬性和方法。這個(gè)等同于的屬性現(xiàn)已棄用。。 前言 生活有度,人生添壽。 原文地址:詳解javascript的類 博主博客地址:Damonare的個(gè)人博客 ??Javascript從當(dāng)初的一個(gè)彈窗語言,一...

    marek 評(píng)論0 收藏0
  • 剖析JS的原型鏈和繼承

    摘要:接下來我們來聊一下的原型鏈繼承和類。組合繼承為了復(fù)用方法,我們使用組合繼承的方式,即利用構(gòu)造函數(shù)繼承屬性,利用原型鏈繼承方法,融合它們的優(yōu)點(diǎn),避免缺陷,成為中最常用的繼承。 JavaScript是一門面向?qū)ο蟮脑O(shè)計(jì)語言,在JS里除了null和undefined,其余一切皆為對(duì)象。其中Array/Function/Date/RegExp是Object對(duì)象的特殊實(shí)例實(shí)現(xiàn),Boolean/N...

    darkerXi 評(píng)論0 收藏0
  • 體驗(yàn)javascript之美第七課 理解原型鏈和擴(kuò)展原型方法

    摘要:原型鏈理解第一件事你不用管其他語言,一句話,你只要記住里面的對(duì)象包含一個(gè)原型,原型是啥,就是另外一個(gè)對(duì)象。原型就相當(dāng)于你家的車棚子,而你的那個(gè)自行車就是對(duì)象。萬事萬物皆對(duì)象有啥用一句話,擴(kuò)展原型方法,給大家一到面試題,數(shù)組去重自己體會(huì)下。 概述 通過上節(jié)課的學(xué)習(xí),大家已經(jīng)會(huì)用一種json的方式定義對(duì)象了,其實(shí)這個(gè)就是傳說中的單體模式,當(dāng)然這個(gè)大家不用記,關(guān)于設(shè)計(jì)模式暫時(shí)不用了解。但是總...

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

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

0條評(píng)論

XboxYan

|高級(jí)講師

TA的文章

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