您好,登錄后才能下訂單哦!
本文小編為大家詳細(xì)介紹“JavaScript的繼承方式是什么”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“JavaScript的繼承方式是什么”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識吧。
emmm...六種?五種?還是四種來著...
這次記清楚了 一共有五種繼承方式
盜用構(gòu)造函數(shù) (經(jīng)典繼承方式 )
組合繼承
原型鏈?zhǔn)嚼^承
寄生式繼承
寄生式組合繼承
基本思路很簡單:在子類構(gòu)造函數(shù)中調(diào)用父類構(gòu)造函數(shù)。因為畢竟函數(shù)就是在特定上下文中執(zhí)行代碼的簡單對象,所以可以使用apply() 和 call() 方法以新創(chuàng)建的對象為上下文執(zhí)行構(gòu)造函數(shù)。
盜用構(gòu)造函數(shù)的一個優(yōu)點就是可以在子類構(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); //實例屬性 this.age = age } let instance1 = new SubType('zxc', 2) let instance2 = new SuperType('gyx') // instance1.sayHi() // ?類也不能訪問父類原型上定義的方法,因此所有類型只能使用構(gòu)造函數(shù)模式 console.log(instance1); // SubType { name: 'zxc', sayName: [Function (anonymous)], age: 2 }
組合繼承(有時候也叫偽經(jīng)典繼承)綜合了原型鏈和盜用構(gòu)造函數(shù),將兩者的優(yōu)點集中了起來。基 本的思路是使用原型鏈繼承原型上的屬性和方法,而通過盜用構(gòu)造函數(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); } 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
原型式繼承適用于這種情況:你有一個對象,想在它的基礎(chǔ)上再創(chuàng)建一個新對象。你需要把這個對象先傳給 object() ,然后再對返回的對象進(jìn)行適當(dāng)修改。
Object.create() 方法將原型式繼承的概念規(guī)范化了 這個方法接收兩個參數(shù):作為新對象原型的對象,以及給新對象定義額外屬性的對象(第二個可選)
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() 的第二個參數(shù)與 Object.defineProperties() 的第二個參數(shù)一樣:每個新增屬性都通過各自的描述符來描述
let anotherPerson = Object.create(person, { name: { value: "Greg" } }); console.log(anotherPerson.name); // "Greg"
寄生式繼承背后的思路類似于寄生構(gòu)造函數(shù)和工廠模式:創(chuàng)建一個實現(xiàn)繼承的函數(shù),以某種方式增強對象,然后返回這個對象。
function createAnother(original) { //通過調(diào)用函數(shù)創(chuàng)建一個對象 let clone = Object(original) clone.sayHi = function () { // 以某種方式增強這個對象 console.log("hi"); }; clone.sayName = function () { // 以某種方式增強這個對象 console.log(this.name); }; return clone; // 返回這個對象 } let person = { name: "Nicholas", friends: ["Shelby", "Court", "Van"] }; let anotherPerson = createAnother(person); anotherPerson.sayHi(); // "hi" anotherPerson.sayName(); // "hi"
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上會有兩個屬性: name 和 colors 。它們都是 SuperType 的實例屬性,但現(xiàn)在成為了 SubType 的原型屬性。在調(diào)用 SubType構(gòu)造函數(shù)時,也會調(diào)用SuperType 構(gòu)造函數(shù),這一次會在新對象上創(chuàng)建實例屬性 name 和 colors 。這兩個實例屬性會遮蔽原型上同名的屬性。
如圖所示,有兩組 name 和 colors 屬性:一組在實例上,另一組在 SubType 的原型上。這是 調(diào)用兩次 SuperType 構(gòu)造函數(shù)的結(jié)果,好在有辦法解決這個問題。
寄生式組合繼承通過盜用構(gòu)造函數(shù)繼承屬性,但使用混合式原型鏈繼承方法?;舅悸肥?strong>不通過調(diào) 用父類構(gòu)造函數(shù)給子類原型賦值,而是取得父類原型的一個副本。說到底就是使用寄生式繼承來繼承父 類原型,然后將返回的新對象賦值給子類原型。寄生式組合繼承的基本模式如下所示:
function inheritPrototype(subType, superType) { let prototype = object(superType.prototype); // 創(chuàng)建對象 prototype.constructor = subType; // 增強對象 subType.prototype = prototype; // 賦值對象 }
這個 inheritPrototype() 函數(shù)實現(xiàn)了寄生式組合繼承的核心邏輯。這個函數(shù)接收兩個參數(shù):子 類構(gòu)造函數(shù)和父類構(gòu)造函數(shù)。在這個函數(shù)內(nèi)部,第一步是創(chuàng)建父類原型的一個副本。然后,給返回的 prototype 對象設(shè)置 constructor 屬性,解決由于重寫原型導(dǎo)致默認(rèn) constructor 丟失的問題。最 后將新創(chuàng)建的對象賦值給子類型的原型。如下例所示,調(diào)用 inheritPrototype() 就可以實現(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 上不必要也用不到的屬性, 因此可以說這個例子的效率更高。而且,原型鏈仍然保持不變,因此 instanceof 操作符和 isPrototypeOf() 方法正常有效。寄生式組合繼承可以算是引用類型繼承的最佳模式。
讀到這里,這篇“JavaScript的繼承方式是什么”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領(lǐng)會,如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。