欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文弄懂JavaScript的繼承方式

 更新時(shí)間:2022年05月10日 16:05:51   作者:悲傷蛙11  
這篇文章主要介紹了一文弄懂JavaScript的繼承方式,在java面試過(guò)程中經(jīng)常被問(wèn)到j(luò)avascript中有幾種繼承方式,每種繼承方式是怎么實(shí)現(xiàn)的,文中給大家講解的非常詳細(xì),需要的朋友可以參考下

JavaScript中的繼承方式

問(wèn):JavaScript中有幾種繼承方式呢

emmm...六種?五種?還是四種來(lái)著...

這次記清楚了 一共有五種繼承方式

  • 盜用構(gòu)造函數(shù) (經(jīng)典繼承方式 )
  • 組合繼承
  • 原型鏈?zhǔn)嚼^承
  • 寄生式繼承
  • 寄生式組合繼承

問(wèn):每種繼承方式是怎么實(shí)現(xiàn)的呢

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

基本思路很簡(jiǎn)單:在子類構(gòu)造函數(shù)中調(diào)用父類構(gòu)造函數(shù)。因?yàn)楫吘购瘮?shù)就是在特定上下文中執(zhí)行代碼的簡(jiǎn)單對(duì)象,所以可以使用apply() 和 call() 方法以新創(chuàng)建的對(duì)象為上下文執(zhí)行構(gòu)造函數(shù)。

盜用構(gòu)造函數(shù)的一個(gè)優(yōu)點(diǎn)就是可以在子類構(gòu)造函數(shù)中向父類構(gòu)造函數(shù)傳參

function SuperType(name) {
  this.name = name
  this.sayName = function () {
      console.log(this.name);
  }
}
function SubType(name, age) {
  //  繼承 SuperType 并傳參
  SuperType.call(this, name);
  //實(shí)例屬性
  this.age = age
}
let instance1 = new SubType('zxc', 2)
let instance2 = new SuperType('gyx')
// instance1.sayHi() // ?類也不能訪問(wèn)父類原型上定義的方法,因此所有類型只能使用構(gòu)造函數(shù)模式
console.log(instance1);  // SubType { name: 'zxc', sayName: [Function (anonymous)], age: 2 }

組合繼承

組合繼承(有時(shí)候也叫偽經(jīng)典繼承)綜合了原型鏈和盜用構(gòu)造函數(shù),將兩者的優(yōu)點(diǎn)集中了起來(lái)?;?本的思路是使用原型鏈繼承原型上的屬性和方法,而通過(guò)盜用構(gòu)造函數(shù)繼承實(shí)例屬性。 這樣既可以把方 法定義在原型上以實(shí)現(xiàn)重用,又可以讓每個(gè)實(shí)例都有自己的屬性。

function SuperType(name) {
    this.name = name
    this.colors = ['red', 'blue', 'green']
}
SuperType.prototype.sayName = function () {
    console.log(this.name);
}
function SubType(name, age) {
    //繼承實(shí)例屬性
    SuperType.call(this, name)
    this.age = age
}
//繼承原型方法
SubType.prototype = new SuperType() 
SubType.prototype.sayAge = function () {
    console.log(this.age);
}
let instance1 = new SubType('zxc', '22')
instance1.sayName()  //zxc
instance1.sayAge()   // 22
let instance2 = new SubType("Greg", 27);
console.log(instance2.colors); // "red,blue,green"
instance2.sayName(); // "Greg";
instance2.sayAge(); // 27

原型鏈?zhǔn)嚼^承

原型式繼承適用于這種情況:你有一個(gè)對(duì)象,想在它的基礎(chǔ)上再創(chuàng)建一個(gè)新對(duì)象。你需要把這個(gè)對(duì)象先傳給 object() ,然后再對(duì)返回的對(duì)象進(jìn)行適當(dāng)修改。

Object.create() 方法將原型式繼承的概念規(guī)范化了 這個(gè)方法接收兩個(gè)參數(shù):作為新對(duì)象原型的對(duì)象,以及給新對(duì)象定義額外屬性的對(duì)象(第二個(gè)可選)

let person = {
   name: "Nicholas",
   age: 12,
   friends: ["Shelby", "Court", "Van"]
};
let anotherPerson1 = Object.create(person);
anotherPerson1.name = 'lll'  
anotherPerson1.friends.push('zxc') 
console.log(anotherPerson1);   // { name: 'lll' }
console.log(person.friends); //[ 'Shelby', 'Court', 'Van', 'zxc' ]

// ? Object.create() 的第二個(gè)參數(shù)與 Object.defineProperties() 的第二個(gè)參數(shù)一樣:每個(gè)新增屬性都通過(guò)各自的描述符來(lái)描述

let anotherPerson = Object.create(person, {
    name: {
        value: "Greg"
    }
});
console.log(anotherPerson.name); // "Greg"

寄生式繼承

寄生式繼承背后的思路類似于寄生構(gòu)造函數(shù)和工廠模式:創(chuàng)建一個(gè)實(shí)現(xiàn)繼承的函數(shù),以某種方式增強(qiáng)對(duì)象,然后返回這個(gè)對(duì)象。

function createAnother(original) {
    //通過(guò)調(diào)用函數(shù)創(chuàng)建一個(gè)對(duì)象
    let clone = Object(original)
    clone.sayHi = function () { // 以某種方式增強(qiáng)這個(gè)對(duì)象
        console.log("hi");
    };
    clone.sayName = function () { // 以某種方式增強(qiáng)這個(gè)對(duì)象
        console.log(this.name);
    };
    return clone; // 返回這個(gè)對(duì)象
}
let person = {
    name: "Nicholas",
    friends: ["Shelby", "Court", "Van"]
};
let anotherPerson = createAnother(person);
anotherPerson.sayHi(); // "hi"
anotherPerson.sayName(); // "hi"

寄生時(shí)組合繼承

function SuperType(name) {
    this.name = name
    this.colors = ['red', 'blue']
}
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);
};
let instance1 = new SubType('zxc', 12)
console.log(instance1);

在上面的代碼執(zhí)行后, SubType.prototype上會(huì)有兩個(gè)屬性: name 和 colors 。它們都是 SuperType 的實(shí)例屬性,但現(xiàn)在成為了 SubType 的原型屬性。在調(diào)用 SubType構(gòu)造函數(shù)時(shí),也會(huì)調(diào)用SuperType 構(gòu)造函數(shù),這一次會(huì)在新對(duì)象上創(chuàng)建實(shí)例屬性 name 和 colors 。這兩個(gè)實(shí)例屬性會(huì)遮蔽原型上同名的屬性。

如圖所示,有兩組 name 和 colors 屬性:一組在實(shí)例上,另一組在 SubType 的原型上。這是 調(diào)用兩次 SuperType 構(gòu)造函數(shù)的結(jié)果,好在有辦法解決這個(gè)問(wèn)題。

寄生式組合繼承通過(guò)盜用構(gòu)造函數(shù)繼承屬性,但使用混合式原型鏈繼承方法。基本思路是不通過(guò)調(diào) 用父類構(gòu)造函數(shù)給子類原型賦值,而是取得父類原型的一個(gè)副本。說(shuō)到底就是使用寄生式繼承來(lái)繼承父 類原型,然后將返回的新對(duì)象賦值給子類原型。寄生式組合繼承的基本模式如下所示:

function inheritPrototype(subType, superType) {
    let prototype = object(superType.prototype); // 創(chuàng)建對(duì)象
    prototype.constructor = subType; // 增強(qiáng)對(duì)象
    subType.prototype = prototype; // 賦值對(duì)象
}

這個(gè) inheritPrototype() 函數(shù)實(shí)現(xiàn)了寄生式組合繼承的核心邏輯。這個(gè)函數(shù)接收兩個(gè)參數(shù):子 類構(gòu)造函數(shù)和父類構(gòu)造函數(shù)。在這個(gè)函數(shù)內(nèi)部,第一步是創(chuàng)建父類原型的一個(gè)副本。然后,給返回的 prototype 對(duì)象設(shè)置 constructor 屬性,解決由于重寫原型導(dǎo)致默認(rèn) constructor 丟失的問(wèn)題。最 后將新創(chuàng)建的對(duì)象賦值給子類型的原型。如下例所示,調(diào)用 inheritPrototype() 就可以實(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;
}
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function () {
    console.log(this.age);
};

這里只調(diào)用了一次 SuperType 構(gòu)造函數(shù),避免了 SubType.prototype 上不必要也用不到的屬性, 因此可以說(shuō)這個(gè)例子的效率更高。而且,原型鏈仍然保持不變,因此 instanceof 操作符和 isPrototypeOf() 方法正常有效。寄生式組合繼承可以算是引用類型繼承的最佳模式。

到此這篇關(guān)于一文弄懂JavaScript的繼承方式的文章就介紹到這了,更多相關(guān)js繼承方式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論