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

資訊專欄INFORMATION COLUMN

JavaScript繼承模式

DrizzleX / 3001人閱讀

摘要:組合繼承組合繼承有時(shí)也叫偽經(jīng)典繼承,該繼承模式將原型鏈和借用構(gòu)造函數(shù)的技術(shù)結(jié)合在一起實(shí)現(xiàn)。寄生組合式繼承通過借用構(gòu)造函數(shù)來繼承屬性,通過原型鏈的混成形式來繼承方法。

原文地址:JavaScript實(shí)現(xiàn)繼承

眾所周知,JavaScript 這門語言在 ES6 出來之前是沒有類(class)這一概念的,所以 JavaScript 中的類都是通過原型鏈來實(shí)現(xiàn)的。同樣,使用 JavaScript 也能實(shí)現(xiàn)面向?qū)ο蟮膶?shí)現(xiàn)繼承。以下是《高程》(第三版)的讀書筆記。

原型鏈

通過原型鏈實(shí)現(xiàn)繼承很容易理解,也很簡(jiǎn)單。將子類的原型指向父類的實(shí)例即可。寫個(gè)簡(jiǎn)單的例子:

// 父類
function SuperType() {
    this.property = "super";
}
// 在父類的原型上定義方法
SuperType.prototype.getSuperVal = function () {
    console.log(this.property);
};

// 子類
function SubType() {
    this.property = "sub";
}
// 子類繼承父類
SubType.prototype = new SuperType();

var instance = new SubType();
console.log(instance.getSuperVal()); // "sub"

對(duì)于子類來講,其原型的指向應(yīng)該是這樣的:SubType -> new SuperType() -> SuperType.prototype -> Object.prototype -> null。

注意:

如果想要給子類添加原型上的方法,需要在子類繼承了父類后添加,否則會(huì)被父類實(shí)例所覆蓋。

也不要用對(duì)象字面量的方式給子類原型添加新方法,這會(huì)使得之前的繼承失效。

原型鏈的問題:

父類的實(shí)例屬性成為了子類的原型屬性,即子類的實(shí)例共享了該父類實(shí)例的屬性,如果該屬性是引用類型,則子類的實(shí)例對(duì)該屬性的修改會(huì)反映在所有的子類實(shí)例上。

在創(chuàng)建子類實(shí)例時(shí),不能向父類的構(gòu)造函數(shù)傳遞參數(shù)。實(shí)際上,應(yīng)該說是沒有辦法在不影響所有對(duì)象實(shí)例的情況下,給父類的構(gòu)造函數(shù)傳遞參數(shù)。

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

這個(gè)方法是為了解決原型鏈方式帶來的問題,使用十分巧妙,利用了 call 方法。代碼實(shí)現(xiàn):

// 父類
function SuperType() {
    this.users = ["Jack", "Tom"];
}
// 子類
function SubType() {
    // 繼承
    SuperType.call(this);
}

var instance1 = new SubType();
var instance2 = new SubType();

instance1.users.pop(); // "Tom"
console.log(instance2.users); // ["Jack", "Tom"]

通過借用構(gòu)造函數(shù)解決了共享原型屬性導(dǎo)致的問題。同時(shí)也可以通過 call 方法給父類傳遞參數(shù)。

借用構(gòu)造函數(shù)的問題:

方法都需要在構(gòu)造函數(shù)(父類或子類)中定義,無法達(dá)到函數(shù)復(fù)用的功能。

組合繼承

組合繼承有時(shí)也叫偽經(jīng)典繼承,該繼承模式將原型鏈和借用構(gòu)造函數(shù)的技術(shù)結(jié)合在一起實(shí)現(xiàn)。示例代碼:

// 父類
function SuperType(company) {
    this.company = company;
    this.staffs = ["Jack", "Tom"];
}
// 父類方法
SuperType.prototype.getCompany = function () {
    console.log(this.company);
};

// 子類
function SubType(company, product) {
    // 繼承屬性
    SuperType.call(this, company);

    this.product = product;
}
// 繼承方法
SubType.prototype = new SuperType();
// 指向正確的constructor
SubType.prototype.constructor = SubType;
SubType.prototype.getProduct = function () {
    console.log(this.product);
};

// SubType實(shí)例
var instance1 = new SubType("A", "tellphone");
instance1.getCompany(); // "A"
instance1.getProduct(); // "tellphone"
instance1.staffs.push("Amy"); // ["Jack", "Tom", "Amy"]

var instance2 = new SubType("B", "toy");
instance2.getCompany(); // "B"
instance2.getProduct(); // "toy"
console.log(instance2.staffs); // ["Jack", "Tom"]

從代碼的例子可以觀察到,組合繼承模式可以讓子類的多個(gè)實(shí)例既能擁有自己的屬性,又能使用相同的方法,融合了原型鏈和借用構(gòu)造函數(shù)的優(yōu)點(diǎn)。

原型式繼承

原型式繼承是借助原型可以基于已有的對(duì)象創(chuàng)建新對(duì)象,同時(shí)還不必因此創(chuàng)建自定義類型。使用如下函數(shù)實(shí)現(xiàn):

function object(obj) {
    function F() {}
    F.prototype = obj;
    return new F();
}

object 函數(shù)對(duì)傳入的對(duì)象實(shí)現(xiàn)了淺復(fù)制。所以對(duì)所有由其創(chuàng)建的實(shí)例都共享了 obj 對(duì)象中的引用屬性。

寄生式繼承

寄生式繼承模式和原型式繼承模式很相似,創(chuàng)建了一個(gè)僅用于封裝繼承過程的函數(shù),在函數(shù)內(nèi)部增強(qiáng)對(duì)象的功能:

function createAnother(obj) {
    var clone = object(obj);
    clone.saySomething = function () {
        alert("Hello world!");
    };

    return clone;
}

function object(obj) {
    function F() {}
    F.prototype = obj;
    return new F();
}

通過 createAnother 函數(shù),對(duì)對(duì)象的功能進(jìn)行增強(qiáng),然而這種方式也沒有達(dá)到函數(shù)復(fù)用的效果,這一點(diǎn)和構(gòu)造函數(shù)模式一樣。

寄生組合式繼承

通過借用構(gòu)造函數(shù)來繼承屬性,通過原型鏈的混成形式來繼承方法。寄生組合模式使用寄生模式來實(shí)現(xiàn)對(duì)父類原型的繼承,再將結(jié)果指定給子類的原型。其基本模式如下:

function inheritPrototype(subType, superType) {
    // 返回父類原型副本并賦值給子類原型
    subType.prototype = object(superType.prototype);
    subType.prototype.constructor = subType;
}

再來看一個(gè)例子:

// 父類
function SuperType(name) {
    this.name = name;
}
// 在父類的原型上定義方法
SuperType.prototype.getName = function () {
    console.log(this.name);
};

// 子類
function SubType(name, age) {
    SuperType.call(this, name);

    this.age = age;
}

// 寄生組合繼承
inheritPrototype(SubType, SuperType);

// 添加子類方法
SubType.prototype.getAge = function () {
    console.log(this.age);
};

和組合繼承模式相比,寄生組合式繼承模式只調(diào)用了一次 SuperType 構(gòu)造函數(shù),也避免了在 SubType.prototype 上創(chuàng)建多余的屬性。開發(fā)人員普遍認(rèn)為寄生組合式繼承是引用類型最理想的繼承范式。

參考書籍

《JavaScript高級(jí)程序設(shè)計(jì)》(第三版)

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

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

相關(guān)文章

  • 理解JavaScript的核心知識(shí)點(diǎn):原型

    摘要:首先,需要來理清一些基礎(chǔ)的計(jì)算機(jī)編程概念編程哲學(xué)與設(shè)計(jì)模式計(jì)算機(jī)編程理念源自于對(duì)現(xiàn)實(shí)抽象的哲學(xué)思考,面向?qū)ο缶幊淌瞧湟环N思維方式,與它并駕齊驅(qū)的是另外兩種思路過程式和函數(shù)式編程。 JavaScript 中的原型機(jī)制一直以來都被眾多開發(fā)者(包括本人)低估甚至忽視了,這是因?yàn)榻^大多數(shù)人沒有想要深刻理解這個(gè)機(jī)制的內(nèi)涵,以及越來越多的開發(fā)者缺乏計(jì)算機(jī)編程相關(guān)的基礎(chǔ)知識(shí)。對(duì)于這樣的開發(fā)者來說 J...

    iKcamp 評(píng)論0 收藏0
  • [譯] 為什么原型繼承很重要

    摘要:使用構(gòu)造函數(shù)的原型繼承相比使用原型的原型繼承更加復(fù)雜,我們先看看使用原型的原型繼承上面的代碼很容易理解。相反的,使用構(gòu)造函數(shù)的原型繼承像下面這樣當(dāng)然,構(gòu)造函數(shù)的方式更簡(jiǎn)單。 五天之前我寫了一個(gè)關(guān)于ES6標(biāo)準(zhǔn)中Class的文章。在里面我介紹了如何用現(xiàn)有的Javascript來模擬類并且介紹了ES6中類的用法,其實(shí)它只是一個(gè)語法糖。感謝Om Shakar以及Javascript Room中...

    xiao7cn 評(píng)論0 收藏0
  • JavaScript代碼復(fù)用模式

    摘要:如下代碼所示,可以使用構(gòu)造函數(shù)來創(chuàng)建父對(duì)象,這樣做的話,自身的屬性和構(gòu)造函數(shù)的原型的屬性都將被繼承。方法繼承自對(duì)象這是中構(gòu)造函數(shù)鏈的一個(gè)示例。 代碼復(fù)用及其原則 代碼復(fù)用,顧名思義就是對(duì)曾經(jīng)編寫過的代碼的一部分甚至全部重新加以利用,從而構(gòu)建新的程序。在談及代碼復(fù)用的時(shí)候,我們首先可以想到的是繼承性。代碼復(fù)用的原則是: 優(yōu)先使用對(duì)象組合,而不是類繼承 在js中,由于沒有類的概念,因此實(shí)例...

    bergwhite 評(píng)論0 收藏0
  • javaScript面向?qū)ο缶幊?繼承(一)

    摘要:組合繼承前面兩種模式的特點(diǎn)類式繼承通過子類的原型對(duì)父類實(shí)例化實(shí)現(xiàn)的,構(gòu)造函數(shù)式繼承是通過在子類的構(gòu)造函數(shù)作用環(huán)境中執(zhí)行一次父類的構(gòu)造函數(shù)來實(shí)現(xiàn)的。 類有三部分 構(gòu)造函數(shù)內(nèi)的,供實(shí)例化對(duì)象復(fù)制用的 構(gòu)造函數(shù)外的,直接通過點(diǎn)語法添加的,供類使用,實(shí)例化對(duì)象訪問不到 類的原型中的,實(shí)例化對(duì)象可以通過其原型鏈間接地訪問到,也是供所有實(shí)例化對(duì)象所共用的。 類式繼承 類的原型對(duì)象的作用就是為類...

    YorkChen 評(píng)論0 收藏0
  • JavaScript設(shè)計(jì)模式-抽象工廠模式

    摘要:抽象類是一種聲明但是不能使用的類,當(dāng)使用時(shí)就會(huì)報(bào)錯(cuò)。但是是靈活的,可以在類的方法中手動(dòng)地拋出錯(cuò)誤來模擬抽象類。 抽象類是一種聲明但是不能使用的類,當(dāng)使用時(shí)就會(huì)報(bào)錯(cuò)。在JavaScript中,abstract還是一個(gè)保留字,不能像傳統(tǒng)的面向?qū)ο笳Z言那樣輕松創(chuàng)建。但是JavaScript是靈活的,可以在類的方法中手動(dòng)地拋出錯(cuò)誤來模擬抽象類。如下: var Car = function(){...

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

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

0條評(píng)論

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