摘要:常用繼承方式主要分為種原型鏈繼承構(gòu)造函數(shù)繼承組合繼承原型式繼承寄生式繼承寄生組合繼承以及繼承多個(gè)對(duì)象。所以說(shuō),構(gòu)造函數(shù)基礎(chǔ)只能繼承父類(lèi)的實(shí)例屬性和方法,不能繼承原型鏈上的屬性和方法。
JavaScript常用繼承方式主要分為(7種):原型鏈繼承、構(gòu)造函數(shù)繼承、組合繼承、原型式繼承、寄生式繼承、寄生組合繼承以及繼承多個(gè)對(duì)象。
1:原型鏈繼承(核心:將父類(lèi)的實(shí)例作為子類(lèi)的原型)基本概念:重寫(xiě)原型對(duì)象,賦予一個(gè)新的對(duì)象的實(shí)例?;舅枷刖褪亲屢粋€(gè)原型對(duì)象指向另一個(gè)父類(lèi)的實(shí)例。
function Super() { //基本數(shù)據(jù)類(lèi)型 this.text = "Hello"; } Super.prototype.getSuperText = function() { return this.text; } function Sub() { this.subText = "Word"; } Sub.prototype = new Super(); const instance = new Sub(); console.log(instance);
特點(diǎn):非常純粹的繼承關(guān)系,實(shí)例是子類(lèi)的實(shí)例,也是父類(lèi)的實(shí)例。父類(lèi)新增原型方法或?qū)傩?,子?lèi)都能訪問(wèn)到。
優(yōu)點(diǎn):簡(jiǎn)單易于操作
缺點(diǎn):對(duì)引用類(lèi)型數(shù)據(jù)操作會(huì)互相(多個(gè)實(shí)例之間)影響
function Super() { //復(fù)雜對(duì)象,也就是引用類(lèi)型 this.value = [1, 2, 3, 4]; } Super.prototype.getSuperValue = function() { return this.value; } function Sub() { this.subText = "Word"; } Sub.prototype = new Super(); const instance1 = new Sub(); const instance2 = new Sub(); instance1.value.push(5); console.log(instance2.value); // (5)?[1, 2, 3, 4, 5]2:構(gòu)造函數(shù)繼承
//定義構(gòu)造函數(shù) function Super(){ this.value = [1, 2, 3, 4]; } //新增屬性getSuperValue Super.prototype.getSuperValue = function() { return this.value; } //sub每次執(zhí)行都要重新調(diào)用 function Sub(){ Super.call(this); } const instance1 = new Sub(); instance1.value.push(5); console.log(instance1.value); // (5)?[1, 2, 3, 4, 5] const instance2 = new Sub(); console.log(instance2.value); // (4)?[1, 2, 3, 4]
構(gòu)造函數(shù)的特點(diǎn):(對(duì)引用數(shù)據(jù)類(lèi)型沒(méi)有影響)上面的代碼輸出instance1是1,2,3,4,5,instance2是1,2,3,4。這是因?yàn)閟ub每次在執(zhí)行時(shí)都是重新調(diào)用了一個(gè)super.call(),而且構(gòu)造函數(shù)在構(gòu)建對(duì)象的過(guò)程中,每次都是創(chuàng)建了一個(gè)新的object,因此每次調(diào)用sub都會(huì)執(zhí)行一遍super,每次執(zhí)行時(shí)都會(huì)有申請(qǐng)一個(gè)新的內(nèi)存空間,所以得到的兩個(gè)value值是不一樣互不影響的。
缺點(diǎn):在整個(gè)構(gòu)造函數(shù)的基礎(chǔ)過(guò)程中,上面的代碼并沒(méi)有使用proto和prototype的屬性,沒(méi)有使用的話那么原型鏈就沒(méi)有接上。所以說(shuō),構(gòu)造函數(shù)基礎(chǔ)只能繼承父類(lèi)的實(shí)例屬性和方法,不能繼承原型鏈上的屬性和方法。
3:組合繼承通過(guò)調(diào)用父類(lèi)構(gòu)造,繼承父類(lèi)的屬性并保留傳參的優(yōu)點(diǎn),然后通過(guò)將父類(lèi)實(shí)例作為子類(lèi)原型,實(shí)現(xiàn)函數(shù)復(fù)用。
保留了構(gòu)造函數(shù)繼承與原型鏈繼承的優(yōu)點(diǎn)。但是執(zhí)行了兩次Person,屬性重復(fù)了。
function Person(name) { this.name = name; this.value = ["head", "body", "legs"]; } Person.prototype.getName = function() { return this.name; }; // 構(gòu)造函數(shù)繼承 function Teacher(name, school){ // 執(zhí)行又一次Person Person.call(this, name); this.school = school; } // 原型鏈繼承 // 執(zhí)行一次Person Teacher.prototype = new Person(); const Eric = new Teacher("Eric",27); Eric.getName(); // 輸出:Eric // prototype構(gòu)造器指回自己 Teacher.prototype.constructor = Teacher; Teacher.prototype.getSchool = function() { return this.school; };
特點(diǎn):既可以繼承實(shí)例屬性和方法,也可以繼承原型屬性和方法。既是子類(lèi)的實(shí)例也是父類(lèi)的實(shí)例,不存在引用屬性共享的問(wèn)題??梢詡鲄ⅲ瘮?shù)可復(fù)用。
缺點(diǎn):調(diào)用兩次父類(lèi)構(gòu)造函數(shù),生成了兩份實(shí)例。
4:原型式繼承借助原型可以基于已有的對(duì)象創(chuàng)建新的對(duì)象,同時(shí)還不必因此創(chuàng)建自定義類(lèi)型。
原理:(本質(zhì))利用一個(gè)空對(duì)象作為一個(gè)中介。
const lakers = { name: "lakers", value: ["Micheal", "Wade", "Kobe"] }; const lakers1 = Object.create(lakers); const lakers2 = Object.create(lakers); lakers1.value.push("Fish"); console.log(lakers);
模擬Object.create()
object.create()原理:用一個(gè)函數(shù)包裝一個(gè)對(duì)象,然后返回這個(gè)函數(shù)的調(diào)用,這個(gè)函數(shù)就變成了一個(gè)可以隨意添增屬性的實(shí)例或?qū)ο蟆?/p>
Object.prototype.create = function(obj) { function Fun() {} Fun.prototype = obj; return new Fun(); }
缺點(diǎn)有兩點(diǎn):第一點(diǎn)是無(wú)法傳遞參數(shù),第二點(diǎn)是引用類(lèi)型存在變量的污染。
5:寄生式繼承寄生式繼承的思路與寄生構(gòu)造函數(shù)和工廠模式類(lèi)似,即創(chuàng)建一個(gè)僅用于封裝繼承過(guò)程的函數(shù)。
目的:在原型式繼承的基礎(chǔ)上,寄生增加了一些新的方法和屬性。
它的特點(diǎn)同原型式繼承一樣,也是無(wú)法傳遞參數(shù),而且引用的數(shù)據(jù)類(lèi)型也容易存在樣式污染。
Object.createNew()
Object.prototype.createNew = function(obj){ var newObj = Object.create(obj); //獲取長(zhǎng)度等于一個(gè)function newObj.getLength = function(){ ... }; return newObj; }6:寄生組合繼承
目的:為了解決數(shù)據(jù)重復(fù)拷貝兩遍的問(wèn)題。
Super只執(zhí)行一次。
//定義Super構(gòu)造函數(shù) function Super(name) { this.name = name; this.value = ["Hello", "Word"]; } //在super的原型鏈添加一個(gè)getName Super.prototype.getName = function() { return this.name; }; //定義Sub function Sub(name, age) { //調(diào)用構(gòu)造函數(shù)繼承 Super.call(this, name); this.age = age; } let prototype = Object.create(Super.prototype); prototype.constructor = Sub; Sub.prototype = prototype; Sub.prototype.getAge = function(){ return this.age; } const instance1 = new Sub("Eric", 23); const instance2 = new Sub("Vico", 23); instance1.value.push("!"); instance2.value.push("!!");7:繼承多個(gè)對(duì)象
借助原型式繼承Object.create拿到SuperClass,也就是父類(lèi),拿到父類(lèi)的prototype之后把它賦給ClassOne,再然后我們將ClassTwo的prototype使用一個(gè)Object.assign,一個(gè)對(duì)象的拷貝,把它拷貝到ClassOne里面來(lái),然后最后ClassOne.prototype.constructor等于ClassOne。
也就是使用一個(gè)Class.assign把所有我們想要繼承的父類(lèi)的prototype全部組合到一起完成一個(gè)拷貝,之后再賦給對(duì)象。
function ClassOne.prototype = Object.create(SuperClass.prototype); Object.assign(ClassOne.prototype, ClassTwo.prototype); ClassOne.prototype.constructor = ClassOne;
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/105852.html
摘要:特點(diǎn)跟借用構(gòu)造函數(shù)模式一樣,每次創(chuàng)建對(duì)象都會(huì)創(chuàng)建一遍方法。缺點(diǎn)寄生組合式繼承使用時(shí)說(shuō)明解決了組合繼承存在的問(wèn)題特點(diǎn)只調(diào)用了一次構(gòu)造函數(shù),并且因此避免了在上面創(chuàng)建不必要的多余的屬性原型鏈還能保持不變還能夠正常使用和缺點(diǎn)參考資料 原型鏈繼承 //父類(lèi) function Person(name, age) { this.name = name; this.age = age; ...
摘要:可以通過(guò)構(gòu)造函數(shù)和原型的方式模擬實(shí)現(xiàn)類(lèi)的功能。原型式繼承與類(lèi)式繼承類(lèi)式繼承是在子類(lèi)型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類(lèi)型的構(gòu)造函數(shù)。寄生式繼承這種繼承方式是把原型式工廠模式結(jié)合起來(lái),目的是為了封裝創(chuàng)建的過(guò)程。 js繼承的概念 js里常用的如下兩種繼承方式: 原型鏈繼承(對(duì)象間的繼承) 類(lèi)式繼承(構(gòu)造函數(shù)間的繼承) 由于js不像java那樣是真正面向?qū)ο蟮恼Z(yǔ)言,js是基于對(duì)象的,它沒(méi)有類(lèi)的概念。...
摘要:原型繼承與類(lèi)繼承類(lèi)繼承是在子類(lèi)型構(gòu)造函數(shù)的內(nèi)部調(diào)用父類(lèi)型的構(gòu)造函數(shù)原型式繼承是借助已有的對(duì)象創(chuàng)建新的對(duì)象,將子類(lèi)的原型指向父類(lèi)。 JavaScript 繼承方式的概念 js 中實(shí)現(xiàn)繼承有兩種常用方式: 原型鏈繼承(對(duì)象間的繼承) 類(lèi)式繼承(構(gòu)造函數(shù)間的繼承) JavaScript不是真正的面向?qū)ο蟮恼Z(yǔ)言,想實(shí)現(xiàn)繼承可以用JS的原型prototype機(jī)制或者call和apply方法 在面...
摘要:原型式繼承利用一個(gè)空對(duì)象作為中介,將某個(gè)對(duì)象直接賦值給空對(duì)象構(gòu)造函數(shù)的原型。其中表示構(gòu)造函數(shù),一個(gè)類(lèi)中只能有一個(gè)構(gòu)造函數(shù),有多個(gè)會(huì)報(bào)出錯(cuò)誤如果沒(méi)有顯式指定構(gòu)造方法,則會(huì)添加默認(rèn)的方法,使用例子如下。 (關(guān)注福利,關(guān)注本公眾號(hào)回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實(shí)戰(zhàn)、面試指導(dǎo))showImg(https://segmentfault.com/img/rem...
摘要:可以看出,這個(gè)查找過(guò)程是一個(gè)鏈?zhǔn)降牟檎?,每個(gè)對(duì)象都有一個(gè)到它自身原型對(duì)象的鏈接,這些鏈接組件的整個(gè)鏈條就是原型鏈。原型的構(gòu)建字面量方式當(dāng)通過(guò)字面量方式創(chuàng)建對(duì)象時(shí),它的原型就是。 面向?qū)ο?JavaScript沒(méi)有類(lèi)(class)的概念的(ES6 中的class也只不過(guò)是語(yǔ)法糖,并非真正意義上的類(lèi)),而在JavaScript中,在 JavaScript 中,除了 String, Numb...
閱讀 2738·2021-11-22 13:54
閱讀 1077·2021-10-14 09:48
閱讀 2302·2021-09-08 09:35
閱讀 1565·2019-08-30 15:53
閱讀 1177·2019-08-30 13:14
閱讀 615·2019-08-30 13:09
閱讀 2531·2019-08-30 10:57
閱讀 3343·2019-08-29 13:18