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

資訊專欄INFORMATION COLUMN

JavaScript六種非常經(jīng)典的對(duì)象繼承方式

sunnyxd / 376人閱讀

摘要:就是這個(gè)原理直接將某個(gè)對(duì)象直接賦值給構(gòu)造函數(shù)的原型。五寄生式繼承重點(diǎn)創(chuàng)建一個(gè)僅用于封裝繼承過(guò)程的函數(shù),該函數(shù)在內(nèi)部以某種方式來(lái)增強(qiáng)對(duì)象,最后返回構(gòu)造函數(shù)。

一、原型鏈繼承

重點(diǎ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;
}
// 繼承自SuperType
SubType.prototype = new SuperType();

SubType.prototype.getSubValue = function (){
  return this.subproperty;
};

var example = new SubType();
alert(example.getSuperValue());//true

使用原型創(chuàng)建對(duì)象會(huì)存在多個(gè)實(shí)例對(duì)引用類型的操作會(huì)被篡改的問(wèn)題,在上面同樣存在這個(gè)問(wèn)題,如下:

function SuperType(){
  this.colors = ["red", "blue", "green"];
}
function SubType(){}//即使沒(méi)有寫(xiě),也不會(huì)影響結(jié)果

SubType.prototype = new SuperType();

var example1 = new SubType();
example1.colors.push("black");
alert(example1.colors); //"red,blue,green,black"

var example2 = new SubType(); 
alert(example.colors); //"red,blue,green,black"

兩個(gè)實(shí)例對(duì)象example1和example2的colors屬性指向相同,改變一個(gè)會(huì)影響另一個(gè)實(shí)例的屬性。

缺點(diǎn):
①原型鏈繼承多個(gè)實(shí)例的引用類型屬性指向相同,一個(gè)實(shí)例修改了原型屬性,另一個(gè)實(shí)例的原型屬性也會(huì)被修改;
②不能傳遞參數(shù);
③繼承單一。

二、借用構(gòu)造函數(shù)繼承

重點(diǎn):使用.call()和.apply()將父類構(gòu)造函數(shù)引入子類函數(shù),使用父類的構(gòu)造函數(shù)來(lái)增強(qiáng)子類實(shí)例,等同于復(fù)制父類的實(shí)例給子類。

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

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

var example1 = new SubType("Mike", 23);
example1.colors.push("black");
alert(example1.colors);//"red,blue,green,black"

var example2 = new SubType();
alert(example2.colors);//"red,blue,green"

alert(example1.name); // "Mike"
alert(example1.age); // 23

借用構(gòu)造函數(shù)繼承的重點(diǎn)就在于SuperType.call(this, name),調(diào)用了SuperType構(gòu)造函數(shù),這樣,SubType的每個(gè)實(shí)例都會(huì)將SuperType中的屬性復(fù)制一份。

缺點(diǎn):
①只能繼承父類的實(shí)例屬性和方法,不能繼承原型屬性/方法;
②無(wú)法實(shí)現(xiàn)構(gòu)造函數(shù)的復(fù)用,每個(gè)子類都有父類實(shí)例函數(shù)的副本,影響性能,代碼會(huì)臃腫。

三、組合繼承

重點(diǎn):將原型鏈繼承構(gòu)造函數(shù)繼承這兩種模式的優(yōu)點(diǎn)組合在一起,通過(guò)調(diào)用父類構(gòu)造,繼承父類的屬性并保留傳參,然后通過(guò)將父類實(shí)例作為子類原型,實(shí)現(xiàn)函數(shù)復(fù)用。

其背后的思路是使用原型鏈實(shí)現(xiàn)對(duì)原型屬性和方法的繼承,而通過(guò)借用構(gòu)造函數(shù)來(lái)實(shí)現(xiàn)對(duì)實(shí)例屬性的繼承,這樣,既通過(guò)在原型上定義方法實(shí)現(xiàn)了函數(shù)復(fù)用,又能保證每個(gè)實(shí)例都有它自己的屬性。

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

function SubType(name, age){
  //繼承屬性
  SuperType.call(this, name);
  this.age = age;
}

// 繼承方法
SubType.prototype = new SuperType(); 
SubType.prototype.constructor = SubType; 
SubType.prototype.sayAge = function(){
    alert(this.age);
};

var example1 = new SubType("Mike", 23);
example1.colors.push("black");
alert(example1.colors); //"red,blue,green,black"
example1.sayName(); //"Mike";
example1.sayAge(); //23

var example2 = new SubType("Jack", 22);
alert(example2.colors); //"red,blue,green"
example2.sayName(); //"Jack";
example2.sayAge(); //22

缺陷:
父類中的實(shí)例屬性和方法既存在于子類的實(shí)例中,又存在于子類的原型中,不過(guò)僅是內(nèi)存占用,因此,在使用子類創(chuàng)建實(shí)例對(duì)象時(shí),其原型中會(huì)存在兩份相同的屬性/方法。-------這個(gè)方法是javascript中最常用的繼承模式。

四、 原型式繼承

重點(diǎn):用一個(gè)函數(shù)包裝一個(gè)對(duì)象,然后返回這個(gè)函數(shù)的調(diào)用,這個(gè)函數(shù)就變成了個(gè)可以隨意增添屬性的實(shí)例或?qū)ο蟆bject.create()就是這個(gè)原理,直接將某個(gè)對(duì)象直接賦值給構(gòu)造函數(shù)的原型。

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

object()對(duì)傳入其中的對(duì)象執(zhí)行了一次淺復(fù)制,將O的原型直接指向傳入的對(duì)象。

var person = {
  name: "Mike",
  friends: ["Jack", "Tom", "Joes"]
};

var anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Peter");

var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("BoBo");

alert(person.friends);   //"Jack,Tom,Joes,Peter,BoBo"

ECMAScript5通過(guò)新增Object.create()方法規(guī)范化了原型式繼承,這個(gè)方法接收兩個(gè)參數(shù):一個(gè)用作新對(duì)象原型的對(duì)象和一個(gè)作為新對(duì)象定義額外屬性的對(duì)象。

var person = {
name:"EvanChen",
friends:["Shelby","Court","Van"];
};
var anotherPerson = Object.create(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
var yetAnotherPerson = Object.create(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
console.log(person.friends);//"Shelby","Court","Van","Rob","Barbie"

缺點(diǎn):
①原型鏈繼承多個(gè)實(shí)例的引用類型屬性指向相同(所有實(shí)例都會(huì)繼承原型上的屬性),存在篡改的可能;
②無(wú)法傳遞參數(shù),無(wú)法實(shí)現(xiàn)復(fù)用。(新實(shí)例屬性都是后面添加的)。

五、寄生式繼承

重點(diǎn):創(chuàng)建一個(gè)僅用于封裝繼承過(guò)程的函數(shù),該函數(shù)在內(nèi)部以某種方式來(lái)增強(qiáng)對(duì)象,最后返回構(gòu)造函數(shù)。(就像給原型式繼承外面套了個(gè)殼子,然后return出來(lái))

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

函數(shù)的主要作用是為構(gòu)造函數(shù)新增屬性和方法,以增強(qiáng)函數(shù)。

var person = {
  name: "Nicholas",
  friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi(); //"hi"

缺點(diǎn):
①原型鏈繼承多個(gè)實(shí)例的引用類型屬性指向相同,存在篡改的可能;
②無(wú)法傳遞參數(shù),沒(méi)用到原型,無(wú)法復(fù)用。

六、寄生組合式繼承

重點(diǎn):通過(guò)借用構(gòu)造函數(shù)傳遞參數(shù)和寄生模式實(shí)現(xiàn)繼承屬性,通過(guò)原型鏈的混成形式來(lái)繼承方法,在函數(shù)中用apply或者call引入另一個(gè)構(gòu)造函數(shù),可傳參。

function inheritPrototype(subType, superType){
  var prototype = Object.create(superType.prototype); //Object.create創(chuàng)建對(duì)象
  prototype.constructor = subType;                    // 增強(qiáng)對(duì)象
  subType.prototype = prototype;                      // 指定對(duì)象
}

// 父類初始化實(shí)例屬性和原型屬性
function SuperType(name){
  this.name = name;
  this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
  alert(this.name);
};

// 借用構(gòu)造函數(shù)傳遞增強(qiáng)子類實(shí)例屬性(支持傳參和避免篡改)
function SubType(name, age){
  SuperType.call(this, name);
  this.age = age;
}

// 將父類原型指向子類
inheritPrototype(SubType, SuperType);

// 新增子類原型屬性
SubType.prototype.sayAge = function(){
  alert(this.age);
}

var example1 = new SubType("abc", 21);
var example2 = new SubType("def", 22);

example1.colors.push("pink"); // ["red", "blue", "green", "pink"]
example1.colors.push("black"); // ["red", "blue", "green", "black"]

寄生組合繼承集合了前面幾種繼承優(yōu)點(diǎn),幾乎避免了上面繼承方式的所有缺陷,是執(zhí)行效率最高也是應(yīng)用面最廣的。

缺點(diǎn):
實(shí)現(xiàn)的過(guò)程相對(duì)繁瑣。

為什么要學(xué)習(xí)這些繼承方式,明明可以直接繼承為什么還要搞這么麻煩?主要是為了學(xué)習(xí)它們的思想,打下更好的基礎(chǔ),為以后閱讀框架源碼,或自己封裝組件甚至框架大有益處。

時(shí)間有點(diǎn)匆忙,沒(méi)有加上ES6的extends,有空再補(bǔ)上。

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

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

相關(guān)文章

  • JavaScript常見(jiàn)六種繼承方式

    摘要:組合繼承也是需要修復(fù)構(gòu)造函數(shù)指向的這種方式融合原型鏈繼承和構(gòu)造函數(shù)的優(yōu)點(diǎn),是中最常用的繼承模式。的繼承機(jī)制完全不同,實(shí)質(zhì)是先將父類實(shí)例對(duì)象的屬性和方法,加到上面所以必須先調(diào)用方法,然后再用子類的構(gòu)造函數(shù)修改。 前言 面向?qū)ο缶幊毯苤匾囊粋€(gè)方面,就是對(duì)象的繼承。A 對(duì)象通過(guò)繼承 B 對(duì)象,就能直接擁有 B 對(duì)象的所有屬性和方法。這對(duì)于代碼的復(fù)用是非常有用的。 大部分面向?qū)ο蟮木幊陶Z(yǔ)言,...

    silvertheo 評(píng)論0 收藏0
  • JavaScript常見(jiàn)六種繼承方式

    摘要:組合繼承也是需要修復(fù)構(gòu)造函數(shù)指向的這種方式融合原型鏈繼承和構(gòu)造函數(shù)的優(yōu)點(diǎn),是中最常用的繼承模式。的繼承機(jī)制完全不同,實(shí)質(zhì)是先將父類實(shí)例對(duì)象的屬性和方法,加到上面所以必須先調(diào)用方法,然后再用子類的構(gòu)造函數(shù)修改。 前言 面向?qū)ο缶幊毯苤匾囊粋€(gè)方面,就是對(duì)象的繼承。A 對(duì)象通過(guò)繼承 B 對(duì)象,就能直接擁有 B 對(duì)象的所有屬性和方法。這對(duì)于代碼的復(fù)用是非常有用的。 大部分面向?qū)ο蟮木幊陶Z(yǔ)言,...

    wyk1184 評(píng)論0 收藏0
  • JavaScript常見(jiàn)六種繼承方式

    摘要:組合繼承也是需要修復(fù)構(gòu)造函數(shù)指向的這種方式融合原型鏈繼承和構(gòu)造函數(shù)的優(yōu)點(diǎn),是中最常用的繼承模式。的繼承機(jī)制完全不同,實(shí)質(zhì)是先將父類實(shí)例對(duì)象的屬性和方法,加到上面所以必須先調(diào)用方法,然后再用子類的構(gòu)造函數(shù)修改。 前言 面向?qū)ο缶幊毯苤匾囊粋€(gè)方面,就是對(duì)象的繼承。A 對(duì)象通過(guò)繼承 B 對(duì)象,就能直接擁有 B 對(duì)象的所有屬性和方法。這對(duì)于代碼的復(fù)用是非常有用的。 大部分面向?qū)ο蟮木幊陶Z(yǔ)言,...

    anyway 評(píng)論0 收藏0
  • JavaScript常見(jiàn)六種繼承方式

    摘要:組合繼承也是需要修復(fù)構(gòu)造函數(shù)指向的這種方式融合原型鏈繼承和構(gòu)造函數(shù)的優(yōu)點(diǎn),是中最常用的繼承模式。的繼承機(jī)制完全不同,實(shí)質(zhì)是先將父類實(shí)例對(duì)象的屬性和方法,加到上面所以必須先調(diào)用方法,然后再用子類的構(gòu)造函數(shù)修改。 前言 面向?qū)ο缶幊毯苤匾囊粋€(gè)方面,就是對(duì)象的繼承。A 對(duì)象通過(guò)繼承 B 對(duì)象,就能直接擁有 B 對(duì)象的所有屬性和方法。這對(duì)于代碼的復(fù)用是非常有用的。 大部分面向?qū)ο蟮木幊陶Z(yǔ)言,...

    helloworldcoding 評(píng)論0 收藏0
  • JS對(duì)象(3)經(jīng)典對(duì)象創(chuàng)建與繼承模式

    摘要:對(duì)象經(jīng)典對(duì)象創(chuàng)建與繼承模式組合模式創(chuàng)建對(duì)象中創(chuàng)建一個(gè)對(duì)象的方式多種多樣,每種方式都有自己缺點(diǎn)或者優(yōu)點(diǎn),具體的可以參考而組合使用構(gòu)造函數(shù)模式和原型模式來(lái)創(chuàng)建自定義類型算是最常見(jiàn)的方式了。 title: JS對(duì)象(3)經(jīng)典對(duì)象創(chuàng)建與繼承模式 date: 2016-09-28 tags: JavaScript 0x01 組合模式創(chuàng)建對(duì)象 JS 中創(chuàng)建一個(gè)對(duì)象的方式多種多樣,...

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

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

0條評(píng)論

sunnyxd

|高級(jí)講師

TA的文章

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