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

資訊專欄INFORMATION COLUMN

《javascript高級(jí)程序設(shè)計(jì)》第六章 讀書筆記 之 javascript繼承的6種方法

孫吉亮 / 2139人閱讀

摘要:繼承的是超類型中構(gòu)造函數(shù)中的屬性,如上繼承了屬性,但沒有繼承原型中的方法。上述造成的結(jié)果是子類型實(shí)例中有兩組超類型的構(gòu)造函數(shù)中定義的屬性,一組在子類型的實(shí)例中,一組在子類型實(shí)例的原型中。

ECMAScript只支持實(shí)現(xiàn)繼承,主要依靠原型鏈來實(shí)現(xiàn)。與實(shí)現(xiàn)繼承對(duì)應(yīng)的是接口繼承,由于script中函數(shù)沒有簽名,所以無法實(shí)現(xiàn)接口繼承。

一、原型鏈

基本思想:利用原型讓一個(gè)引用類型繼承另一個(gè)引用類型的屬性和方法。
構(gòu)造函數(shù)、原型和實(shí)例的關(guān)系:每一個(gè)構(gòu)造函數(shù)都有一個(gè)原型對(duì)象,原型對(duì)象都包含一個(gè)指向構(gòu)造函數(shù)的指針,而實(shí)例都包含一個(gè)紙箱原型對(duì)象的內(nèi)部指針。
基本用法:

function SuperType() {
    this.property = true;
}

SuperType.prototype.getSuperValue = function () {
    return this.property;
}

function SubType() {
    this.subproperty = false;
}
// 子的原型是父的對(duì)象
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function () {
    return this.subproperty;
}
var instance = new SubType();
console.log(instance.getSuperValue()); // true

關(guān)系圖:

但實(shí)際上,SuperType也有自己的原型,就是Object,這個(gè)原型是默認(rèn)的。
所有函數(shù)的默認(rèn)原型都是Object的實(shí)例,因此默認(rèn)原型都會(huì)包含一個(gè)內(nèi)部指針,指向Object.prototype。
所以完整的關(guān)系圖應(yīng)該是

使用原型能夠做到繼承,但實(shí)際中并不多帶帶使用原型鏈來實(shí)現(xiàn)繼承,原因如下:
1、對(duì)于不需要‘父親’的私有屬性的繼承:我們知道原型來創(chuàng)建對(duì)象,使得所有的實(shí)例都擁有這些共享的屬性和方法,我們?cè)谑褂迷玩渷砝^承最主要的是SubType的原型變?yōu)镾uperType的實(shí)例對(duì)象,那么本來是Super實(shí)例私有的屬性property,且處于SubType的原型中成為SubType實(shí)例的共享屬性。
2、對(duì)于需要‘父親‘私有屬性的繼承:同一,我們知道會(huì)繼承父親的私有屬性,但我們無法通過傳入?yún)?shù)到’父親‘的構(gòu)造函數(shù)來實(shí)現(xiàn)屬性特有值的目的。
鑒于以上我們開始使用第二種繼承方式。

二、借用構(gòu)造函數(shù)(偽造對(duì)象、經(jīng)典繼承)

基本思想:在子類型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型構(gòu)造函數(shù)

function SuperType() {
    this.colors = ["red", "yellow", "black"];
}

SuperType.prototype.getColor = function () {
    return this.colors;
}

function SubType() {
    // 繼承了SuperType
    SuperType.call(this);
}

var instance1 = new SubType();
instance1.colors.push("pink"); // ["red", "yellow", "black","pink"]
console.log(instance1.colors);
var instance2 = new SubType();
console.log(instance2.colors); // ["red", "yellow", "black"]
console.log(instance2 instanceof SuperType); // false
console.log(instance2.getColor()); // instance2.getColor is not a function

此方法是在子類型中調(diào)用了超(父)類型的構(gòu)造函數(shù),使構(gòu)造函數(shù)中的屬性初始化了。
繼承的是超類型中構(gòu)造函數(shù)中的屬性,如上繼承了colors屬性,但沒有繼承SuperType原型中的getcolor方法。
使用此方法,我們還可以傳遞參數(shù)對(duì)屬性進(jìn)行初始化

function SuperType(age) {
    this.age=age;
}

function SubType() {
    // 繼承了SuperType
    SuperType.call(this,18);
}

var instance1 = new SubType();
console.log(instance1.age); // 18

如果需要確保SuperType構(gòu)造函數(shù)不會(huì)重寫子類型的屬性,可以在調(diào)用超類型構(gòu)造函數(shù)后,再添加應(yīng)該在子類型定義的屬性。
缺點(diǎn):
1、超類型的原型不可見
2、所有屬性方法都必須寫在構(gòu)造函數(shù)中,所有類型都只能使用構(gòu)造函數(shù)模式創(chuàng)建

三、組合繼承(偽經(jīng)典繼承)

將原型鏈和借用構(gòu)造函數(shù)的技術(shù)組合到一塊。
思想:使用原型鏈實(shí)現(xiàn)對(duì)原型屬性和方法的繼承,借用構(gòu)造函數(shù)實(shí)現(xiàn)對(duì)實(shí)例屬性的繼承。

function SuperType(age) {
    this.age = age;
}

SuperType.prototype.getAge = function () {
    return this.age;
}

function SubType(age) {
    // 繼承了SuperType
    SuperType.call(this, age);
}

SubType.prototype = new SuperType(20);
var instance1 = new SubType(18);
console.log(instance1.age); // 18
console.log(instance1.getAge()); // 18
console.log(instance1.__proto__.age); // 20
var instance2 = new SubType(17);
instance2.__proto__.age=55;
console.log(instance1.__proto__.age); // 55
console.log(instance2.__proto__.age); // 55

我們可以看到,實(shí)際上instance1和instance2的原型上仍然存在屬于SuperType的實(shí)例屬性的屬性。只是instance1和instance2有了各自的age屬性,不會(huì)再往原型上找。
instanceof和isPrototypeOf()也能夠用于識(shí)別基于組合繼承創(chuàng)建的對(duì)象。
組合繼承避免了原型鏈和借用構(gòu)造函數(shù)的缺陷并融合了兩者的有點(diǎn),成為js中最常用的繼承模式。

四、原型式繼承

思想:借助原型可以基于已有的對(duì)象創(chuàng)建新的對(duì)象,同時(shí)還不必因此創(chuàng)建自定義類型。

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

}

var person = {
    name: "linda",
    friends: ["lily", "shirley"]
};
var antherPerson = object(person);
antherPerson.friends.push("tom");
console.log(antherPerson.name); // linda
console.log(antherPerson.friends); // ["lily", "shirley", "tom]

這個(gè)方法和原型方法原理一樣,只不過把子類型的原型設(shè)置成超類型的實(shí)例對(duì)象包含在方法object中。
ECMAScript5中新增了object.create()方法來規(guī)范原型式繼承(作用與上述object函數(shù)作用類似),第一個(gè)參數(shù)是想要繼承的超類型的實(shí)例對(duì)象,第二個(gè)參數(shù)是子類型所具有的屬性。

var person={
    name:"lily",
    age:12
}
var anotherPerson=Object.create(person,{name:{value:"linda"}});
console.log(anotherPerson.name); // "linda"

第二個(gè)參數(shù)的寫法必須如上的格式。
支持Object.create()方法的瀏覽器有ie9+,F(xiàn)irefox4.+、Safari5+、Opera12+和Chrome

五、寄生式繼承

思想:與寄生構(gòu)造函數(shù)和工廠模式類似,即創(chuàng)建一個(gè)僅用于封裝繼承過程的函數(shù),該函數(shù)在內(nèi)部以某種方式來增強(qiáng)對(duì)象,最后再像真的是它做了所有工作一樣返回對(duì)象。
代碼:

function object(o){
    function F(){}
    F.prototype=o;
    return new F();
}
var person = {
    name: "lily",
    age: 12
}
function createAnotherPerson(original){
    var clone=object(original);
    clone.sayHi=function(){
        console.log("hi");
    }
    return clone;
}
var anotherPerson =createAnotherPerson(person);
anotherPerson.sayHi(); // "hi"
console.log(anotherPerson.name); // "linda"
六、寄生組合式繼承

組合繼承是js最常用的繼承模式,可以結(jié)合不同的模式的優(yōu)點(diǎn),但組合繼承,每次都會(huì)調(diào)用兩次超類型構(gòu)造函數(shù):一次是在創(chuàng)建子類型原型的時(shí)候,另一次是在子類型構(gòu)造函數(shù)內(nèi)部。
上述造成的結(jié)果是子類型實(shí)例中有兩組超類型的構(gòu)造函數(shù)中定義的屬性,一組在子類型的實(shí)例中,一組在子類型實(shí)例的原型中。寄生組合式繼承可以解決上述缺點(diǎn)。

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

Super.prototype.sayName = function () {
    console.log(this.name);
}

function Sub(age) {
    Super.call(this, "linda");
    this.age = age;
}

Sub.prototype = new Super();
Sub.constructor = Sub;
var type=new Sub();
type.sayName(); // "linda"
console.log(type.name); // "linda"
console.log(type.__proto__.name); // undefined

思想:借用構(gòu)造函數(shù)來繼承屬性,借用原型鏈來繼承方法。即繼承超類型的原型,然后再將結(jié)果指定給子類型的原型。
封裝一下即:

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

Super.prototype.sayName = function () {
    console.log(this.name);
}

function Sub(age) {
    Super.call(this, "linda");
    this.age = age;
}

function object(o) {
    function F() {
    }

    F.prototype = o;
    return new F();
}

function inheritPrototype(subType, superType) {
    var prototype = object(superType.prototype); // 創(chuàng)建對(duì)象
    prototype.constructor = subType; // 增強(qiáng)對(duì)象
    subType.prototype = prototype; // 指定對(duì)象
}
inheritPrototype(Sub, Super);
var type = new Sub();
type.sayName(); // "linda"
console.log(type.name); // "linda"
console.log(type.__proto__.name); // undefined

這個(gè)模式的優(yōu)點(diǎn)體現(xiàn)在
1、只調(diào)用了一次Super構(gòu)造函數(shù),高效率
2、避免了在Sub.prototype上面創(chuàng)建不必要的多余的屬性
3、原型鏈保持不變

開發(fā)人員普遍認(rèn)為寄生組合式繼承是引用類型最理想的繼承范式

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

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

相關(guān)文章

  • javascript高級(jí)程序設(shè)計(jì)六章 讀書筆記 javascript對(duì)象創(chuàng)建方式

    摘要:三種使用構(gòu)造函數(shù)創(chuàng)建對(duì)象的方法和的作用都是在某個(gè)特殊對(duì)象的作用域中調(diào)用函數(shù)。這種方式還支持向構(gòu)造函數(shù)傳遞參數(shù)。叫法上把函數(shù)叫做構(gòu)造函數(shù),其他無區(qū)別適用情境可以在特殊的情況下用來為對(duì)象創(chuàng)建構(gòu)造函數(shù)。 一、工廠模式 工廠模式:使用字面量和object構(gòu)造函數(shù)會(huì)有很多重復(fù)代碼,在此基礎(chǔ)上改進(jìn)showImg(https://segmentfault.com/img/bVbmKxb?w=456&...

    xiaotianyi 評(píng)論0 收藏0
  • 高程讀書筆記 六章 面向?qū)ο?em>程序設(shè)計(jì)

    摘要:創(chuàng)建一個(gè)新對(duì)象將構(gòu)造函數(shù)的作用域賦給新對(duì)象因此就指向了這個(gè)新對(duì)象執(zhí)行構(gòu)造函數(shù)中的代碼為這個(gè)新對(duì)象添加屬性返回新對(duì)象。 本章內(nèi)容 理解對(duì)象屬性 理解并創(chuàng)建對(duì)象 理解繼承 ECMA-262把對(duì)象定義為:無序?qū)傩缘募希鋵傩钥梢园局?、?duì)象或者函數(shù) 理解對(duì)象 創(chuàng)建對(duì)象 創(chuàng)建自定義對(duì)象的最簡(jiǎn)單方式就是創(chuàng)建一個(gè)Object的實(shí)例,再為它添加屬性和方法。 var person = new...

    468122151 評(píng)論0 收藏0
  • JS高程讀書筆記--六章原型繼承

    摘要:高程讀書筆記第六章理解對(duì)象創(chuàng)建自定義對(duì)象的方式有創(chuàng)建一個(gè)實(shí)例,然后為它添加屬性和方法。創(chuàng)建了自定義的構(gòu)造函數(shù)之后,其原型對(duì)象默認(rèn)只會(huì)取得屬性至于其他方法都是從繼承而來的。 JS高程讀書筆記--第六章 理解對(duì)象 創(chuàng)建自定義對(duì)象的方式有創(chuàng)建一個(gè)Object實(shí)例,然后為它添加屬性和方法。還可用創(chuàng)建對(duì)象字面量的方式 屬性類型 ECMAScript在定義只有內(nèi)部采用的特性時(shí),描述了屬性的各種特征...

    EasonTyler 評(píng)論0 收藏0
  • 《java 8 實(shí)戰(zhàn)》讀書筆記 -六章 用流收集數(shù)據(jù)

    摘要:分區(qū)函數(shù)返回一個(gè)布爾值,這意味著得到的分組的鍵類型是,于是它最多可以分為兩組是一組,是一組。當(dāng)遍歷到流中第個(gè)元素時(shí),這個(gè)函數(shù)執(zhí)行時(shí)會(huì)有兩個(gè)參數(shù)保存歸約結(jié)果的累加器已收集了流中的前個(gè)項(xiàng)目,還有第個(gè)元素本身。 一、收集器簡(jiǎn)介 把列表中的交易按貨幣分組: Map transactionsByCurrencies = transactions.stream().collect(groupi...

    Airy 評(píng)論0 收藏0
  • 《Python基礎(chǔ)教程》六章--讀書筆記

    摘要:第六章抽象本章會(huì)介紹如何將語句組織成函數(shù)。關(guān)鍵字參數(shù)和默認(rèn)值目前為止,我們使用的參數(shù)都是位置參數(shù),因?yàn)樗鼈兊奈恢煤苤匾聦?shí)上比它們的名字更重要。參數(shù)前的星號(hào)將所有值放置在同一個(gè)元祖中。函數(shù)內(nèi)的變量被稱為局部變量。 第六章:抽象 本章會(huì)介紹如何將語句組織成函數(shù)。還會(huì)詳細(xì)介紹參數(shù)(parameter)和作用域(scope)的概念,以及遞歸的概念及其在程序中的用途。 懶惰即美德 斐波那契數(shù)...

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

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

0條評(píng)論

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