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

資訊專欄INFORMATION COLUMN

《javascript高級(jí)程序設(shè)計(jì)》 繼承實(shí)現(xiàn)方式

cppprimer / 1754人閱讀

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

這篇本來應(yīng)該是作為寫JS 面向?qū)ο蟮那白啵皇亲鳛椤秊avascript高級(jí)程序設(shè)計(jì)》繼承一章的筆記

原型鏈

code 實(shí)現(xiàn)

function SuperType() {
  this.colors = ["red","blue", "green"];
}
function SubType() {
}
SubType.prototype = new SuperType();
var instance1 = new SubType();
instance1.colors.push("black");
console.log(instance1.colors); // ["red","blue", "green","black"]

var instance2 = new SubType();
console.log(instance2.colors); // ["red","blue", "green","black"]

var instance = new SuperType();
console.log(instance.colors); // ["red","blue", "green"]

使用原型鏈來實(shí)現(xiàn)繼承,原型實(shí)際上會(huì)變成另一個(gè)類型的實(shí)例,于是,原先的實(shí)例屬性,會(huì)變成現(xiàn)在的原型屬性了

在創(chuàng)建子類的實(shí)例時(shí),不能向父類的構(gòu)造函數(shù)中傳遞參數(shù)

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

code 實(shí)現(xiàn)繼承

function SuperType() {
  this.colors = ["red","blue","green"];
}
function SubType() {
  SuperType.call(this);
}

var instance1 = new SubType();
instance1.colors.push("black");
console.log(instance1.colors); // ["red", "blue", "green", "black"]

var instance2 = new SubType();
console.log(instance2.colors); // ["red", "blue", "green"]

var instance = new SuperType();
console.log(instance.colors); // ["red","blue", "green"]

同樣也可以實(shí)現(xiàn)參數(shù)的傳遞

function SuperType(name) {
  this.name = name;
}
function SubType(){
  SuperType.call(this, "jack");
  this.age = 29;
}

var instance = new SubType();
console.log(instance.name); // jack
console.log(instance.age); // 29

如果僅僅是借用構(gòu)造函數(shù),那么將無法避免構(gòu)造函數(shù)模式存在的問題--方法都在構(gòu)造函數(shù)中定義,因此,函數(shù)復(fù)用也就無從談起了。而且,在超類型的原型中定義的方法,對(duì)子類而言也是不可見的,結(jié)果所有類型都只能使用構(gòu)造函數(shù)模式。

組合繼承

將原型鏈和借用構(gòu)造函數(shù)的技術(shù)組合到一塊,從而發(fā)回二者之長的一種繼承模式。其背后的思路是使用原型鏈實(shí)現(xiàn)對(duì)原型屬性和方法的繼承,而通過借用構(gòu)造函數(shù)來實(shí)現(xiàn)對(duì)實(shí)例屬性的繼承。這樣,即通過在原型上定義方法實(shí)現(xiàn)了函數(shù)復(fù)用,又能夠保證每個(gè)實(shí)例都有它自己的屬性。

code 實(shí)現(xiàn)

function SuperType(name) {
  this.name = name;
  this.colors = ["red","blue","green"];
}
SuperType.prototype.sayName = function() {
  console.log(this.name);
};
function SubType(name, age) {
  SuperType.call(this, name);
  this.age = age;
};

SubType.prototype = new SuperType();
SubType.prototype.sayAge = function(){
  console.log(this.age);
};

var instance1 = new SubType("jack", 29);
instance1.colors.push("black");
console.log(instance1.colors); //["red", "blue", "green", "black"]
instance1.sayName(); // jack
instance1.sayAge(); // 29

var instance2 = new SubType("allen", 23);
console.log(instance2.colors); // ["red", "blue", "green"]
instance2.sayName(); //allen
instance2.sayAge(); // 23

instanceOfisPrototypeOf 也能夠用于識(shí)別基于組合繼承創(chuàng)建的對(duì)象

原型式繼承

沒有嚴(yán)格意義上的構(gòu)造函數(shù),通過借助原型,可以基于已有的對(duì)象創(chuàng)建新對(duì)象,同時(shí)還不必因此創(chuàng)建自定義類型

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

object() 函數(shù)內(nèi)部,先創(chuàng)建了一個(gè)臨時(shí)性的構(gòu)造函數(shù),然后將傳入的對(duì)象作為這個(gè)構(gòu)造函數(shù)的原型,最后返回這個(gè)臨時(shí)類型的一個(gè)新實(shí)例。從本質(zhì)上將,object() 對(duì)傳入其中的對(duì)象執(zhí)行了一次淺復(fù)制

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

var person = {
    name:"jack",
    friends:["allen","lucy","van"]
}

var anotherPerson = object(person);
anotherPerson.name = "bob";
anotherPerson.friends.push("steve");

var yetAnotherPerson = object(person);
yetAnotherPerson.name = "linda";
yetAnotherPerson.friends.push("shelly")

console.log(person.friends); //["allen", "lucy", "van", "steve", "shelly"]

這種原型式繼承,要求你必須有一個(gè)對(duì)象可以作為另一個(gè)對(duì)象的基礎(chǔ)。如果有這么一個(gè)對(duì)象的話,可以把他傳遞給object() 函數(shù),然后再根據(jù)具體需求對(duì)得到的對(duì)象加以修飾即可。

ECMAScript5 通過Object.create() 方法規(guī)范花了原型式繼承。這個(gè)方法接受兩個(gè)參數(shù):一個(gè)用作新對(duì)象原型的對(duì)象和(可選的)一個(gè)為新對(duì)象定義額外屬性的對(duì)象。在傳入一個(gè)參數(shù)的情況下,Object,create()object() 函數(shù)方法的行為相同

在沒有必要?jiǎng)?chuàng)建構(gòu)造函數(shù),而只是想讓一個(gè)對(duì)象與另一個(gè)對(duì)象保持類似的情況下,原型式繼承是完全可以勝任的。不過,包含引用類型值的屬性始終都會(huì)共享響應(yīng)的值,就像使用原型模式一樣

寄生式繼承

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

function createAnother(original){
  var clone = object(original); // 通過調(diào)用 object() 函數(shù)創(chuàng)建一個(gè)新對(duì)象
  clone.sayHi = function(){  // 以某種方式來增強(qiáng)對(duì)象
    alert("hi");
  };
  return clone; // 返回這個(gè)對(duì)象
}

在主要考慮對(duì)象而不是自定義類型和構(gòu)造函數(shù)的情況下,寄生式繼承也是一種有用的模式。前面示范繼承模式時(shí)使用的object() 函數(shù)不是必需的;任何能夠返回新對(duì)象的函數(shù)都使用與此模式。

寄生組合式繼承

組合繼承是JavaScript 最常用的繼承模式;不過也有自己的不足。組合繼承最大的問題就是無論什么情況下,都會(huì)調(diào)用兩次父類的構(gòu)造函數(shù):一次是在創(chuàng)建子類原型的時(shí)候,另一次是在子類構(gòu)造函數(shù)內(nèi)部。

子類最終會(huì)包含父類對(duì)象的全部實(shí)例屬性,但我們不得不在調(diào)用子類構(gòu)造函數(shù)時(shí)重寫這些屬性。

function SuperType(name) {
    this.name = name;
    this.colors = ["red","blue","green"];
}

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

function SubType(name, age) {
    SuperType.call(this, name); // 第二次調(diào)用 SuperType()
    this.age = age;
}

SubType.prototype = new SuperType(); // 第一次調(diào)用 SuperType()
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function() {
    console.log(this.age);
};

第一次調(diào)用SuperType 構(gòu)造函數(shù)時(shí),SubType.prototype會(huì)得到兩個(gè)屬性:namecolors,他們都是SuperType 的實(shí)例屬性,只不過現(xiàn)在位于SubType 的原型中。當(dāng)調(diào)用SubType 構(gòu)造函數(shù)時(shí),又會(huì)調(diào)用一次SuperType 構(gòu)造函數(shù),這一次又在新對(duì)象上創(chuàng)建了實(shí)例屬性namecolors。 于是,這兩個(gè)屬性就屏蔽了原型中的兩個(gè)同名屬性。

?

所謂寄生組合式繼承,即通過借用構(gòu)造函數(shù)來繼承屬性,通過原型鏈的混成形式來繼承方法。其背后的基本思路是:不必為了指定子類的原型而調(diào)用父類的構(gòu)造函數(shù),我們所需要的無非就是父類原型的一個(gè)副本而已。本質(zhì)上,就是使用寄生式繼承來繼承父類型的原型,然后再將結(jié)果指定給子類的原型。寄生組合式繼承的基本模式如下

function inheritPrototype(subType, superType) {
  var prototype = object(superType.prototype);
  prototype.constructor = subType;
  subType.prototype = prototype;
}

第一步是創(chuàng)建父類原型的一個(gè)副本,第二步是為創(chuàng)建的副本添加constructor 屬性,從而彌補(bǔ)因重寫原型而失去的默認(rèn)的constructor 屬性。第三步是將新創(chuàng)建的對(duì)象(即副本)賦值給子類的原型。

function SuperType(name) {
    this.name = name;
    this.colors = ["red","blue","green"];
}

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

function SubType(name, age) {
    SuperType.call(this, name); // 第二次調(diào)用 SuperType()
    this.age = age;
}

inheritPrototype(SubType, SuperType)
SubType.prototype.sayAge = function() {
    console.log(this.age);
};

這個(gè)例子的高效率體現(xiàn)在它只調(diào)用了一次SuperType 構(gòu)造函數(shù),并且因此避免了在SubType.prototype 上創(chuàng)建不必要的、多余的屬性。于此同時(shí),原型鏈還能保持不變;因此,還能夠正常使用instanceofisPrototypeOf() 。開發(fā)人員普遍認(rèn)為寄生組合繼承是引用類型最理想的繼承范式。

優(yōu)缺點(diǎn)

原型鏈會(huì)修改父類的屬性,在創(chuàng)建子類的實(shí)例時(shí),不能向父類的構(gòu)造函數(shù)中傳遞參數(shù)

借用構(gòu)造函數(shù),則沒有繼承

組合繼承(原型繼承+借用構(gòu)造函數(shù)) 組合繼承最大的問題就是無論什么情況下,都會(huì)調(diào)用兩次父類的構(gòu)造函數(shù):一次是在創(chuàng)建子類原型的時(shí)候,另一次是在子類構(gòu)造函數(shù)內(nèi)部。

原型式繼承,要求你必須有一個(gè)對(duì)象可以作為另一個(gè)對(duì)象的基礎(chǔ),
包含引用類型值的屬性始終都會(huì)共享響應(yīng)的值,就像使用原型模式一樣

寄生式繼承
在主要考慮對(duì)象而不是自定義類型和構(gòu)造函數(shù)的情況下,寄生式繼承也是一種有用的模式

寄生組合式繼承 (這是最成熟的方法,也是現(xiàn)在庫實(shí)現(xiàn)的方法)
第一步是創(chuàng)建父類原型的一個(gè)副本,第二步是為創(chuàng)建的副本添加constructor?屬性,從而彌補(bǔ)因重寫原型而失去的默認(rèn)的constructor?屬性。第三步是將新創(chuàng)建的對(duì)象(即副本)賦值給子類的原型。

?

JS面向?qū)ο笙盗?/p>

prototype.js 是如何實(shí)現(xiàn)JS的類以及類的相關(guān)屬性和作用

Mootools.js 是如何實(shí)現(xiàn)類,以及類的相關(guān)屬性和作用

klass 是如何實(shí)現(xiàn)JS的類以及類的相關(guān)屬性和作用

總結(jié):prototype.js,Mootools.js和klass.js 實(shí)現(xiàn)類的方法的異同與優(yōu)劣

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

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

相關(guān)文章

  • javascript高級(jí)程序設(shè)計(jì)》筆記:繼承

    摘要:繼承和前面兩篇文章中的知識(shí)非常相關(guān),如果對(duì)函數(shù)創(chuàng)建原理和原型鏈不熟悉,請(qǐng)猛戳高級(jí)程序設(shè)計(jì)筆記創(chuàng)建對(duì)象高級(jí)程序設(shè)計(jì)筆記原型圖解繼承,通俗的說,就是將自身不存在的屬性或方法,通過某種方式為自己所用文章分別介紹原型鏈繼承繼承借用構(gòu)造函數(shù)繼承組合繼 繼承和前面兩篇文章中的知識(shí)非常相關(guān),如果對(duì)函數(shù)創(chuàng)建原理和原型鏈不熟悉,請(qǐng)猛戳:《javascript高級(jí)程序設(shè)計(jì)》筆記:創(chuàng)建對(duì)象《javascri...

    JerryC 評(píng)論0 收藏0
  • 《你不知道的javascript》筆記_對(duì)象&原型

    摘要:上一篇你不知道的筆記寫在前面這是年第一篇博客,回顧去年年初列的學(xué)習(xí)清單,發(fā)現(xiàn)僅有部分完成了。當(dāng)然,這并不影響年是向上的一年在新的城市穩(wěn)定連續(xù)堅(jiān)持健身三個(gè)月早睡早起游戲時(shí)間大大縮減,學(xué)會(huì)生活。 上一篇:《你不知道的javascript》筆記_this 寫在前面 這是2019年第一篇博客,回顧去年年初列的學(xué)習(xí)清單,發(fā)現(xiàn)僅有部分完成了。當(dāng)然,這并不影響2018年是向上的一年:在新的城市穩(wěn)定、...

    seasonley 評(píng)論0 收藏0
  • 【10】JavaScript 面向?qū)ο?em>高級(jí)——繼承模式

    摘要:面向?qū)ο蟾呒?jí)繼承模式一原型鏈繼承方式原型鏈繼承流程定義父類型構(gòu)造函數(shù)。缺點(diǎn)無法避免構(gòu)造函數(shù)模式存在的問題方法都在構(gòu)造函數(shù)中定義,無法函數(shù)復(fù)用。六寄生組合式繼承在這里重復(fù)一下組合繼承的代碼組合繼承最大的缺點(diǎn)是會(huì)調(diào)用兩次父構(gòu)造函數(shù)。 JavaScript 面向?qū)ο蟾呒?jí)——繼承模式 一、原型鏈繼承 方式1: 原型鏈繼承 (1)流程: ? 1、定義父類型構(gòu)造函數(shù)。 ? ...

    0xE7A38A 評(píng)論0 收藏0
  • Javascript繼承淺析

    摘要:推薦高級(jí)程序設(shè)計(jì),對(duì)類繼承有詳細(xì)介紹。書中涉及繼承方式多達(dá)數(shù)種,意味著繼承的靈活性。假設(shè)類和類不同公司有不同的公司信息,而同一公司內(nèi)的員工則需要繼承相同的公司信息。組合繼承組合繼承可以認(rèn)為是以上兩種組合實(shí)現(xiàn)。 前言 高級(jí)語言基本上都有類的概念,而javascript因?yàn)楦鞣N原因相對(duì)比較特別,并沒有明確的class類聲明方式(ES6暫不涉及),而是通過構(gòu)造函數(shù)變相實(shí)現(xiàn)。推薦《javas...

    Jochen 評(píng)論0 收藏0
  • javascript高級(jí)程序設(shè)計(jì)》第六章 讀書筆記 之 javascript繼承的6種方法

    摘要:繼承的是超類型中構(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è)引用...

    孫吉亮 評(píng)論0 收藏0

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

0條評(píng)論

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