摘要:常用繼承方式主要分為種原型鏈繼承構造函數繼承組合繼承原型式繼承寄生式繼承寄生組合繼承以及繼承多個對象。所以說,構造函數基礎只能繼承父類的實例屬性和方法,不能繼承原型鏈上的屬性和方法。
JavaScript常用繼承方式主要分為(7種):原型鏈繼承、構造函數繼承、組合繼承、原型式繼承、寄生式繼承、寄生組合繼承以及繼承多個對象。
1:原型鏈繼承(核心:將父類的實例作為子類的原型)基本概念:重寫原型對象,賦予一個新的對象的實例。基本思想就是讓一個原型對象指向另一個父類的實例。
function Super() { //基本數據類型 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);
特點:非常純粹的繼承關系,實例是子類的實例,也是父類的實例。父類新增原型方法或屬性,子類都能訪問到。
優點:簡單易于操作
缺點:對引用類型數據操作會互相(多個實例之間)影響
function Super() { //復雜對象,也就是引用類型 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:構造函數繼承
//定義構造函數 function Super(){ this.value = [1, 2, 3, 4]; } //新增屬性getSuperValue Super.prototype.getSuperValue = function() { return this.value; } //sub每次執行都要重新調用 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]
構造函數的特點:(對引用數據類型沒有影響)上面的代碼輸出instance1是1,2,3,4,5,instance2是1,2,3,4。這是因為sub每次在執行時都是重新調用了一個super.call(),而且構造函數在構建對象的過程中,每次都是創建了一個新的object,因此每次調用sub都會執行一遍super,每次執行時都會有申請一個新的內存空間,所以得到的兩個value值是不一樣互不影響的。
缺點:在整個構造函數的基礎過程中,上面的代碼并沒有使用proto和prototype的屬性,沒有使用的話那么原型鏈就沒有接上。所以說,構造函數基礎只能繼承父類的實例屬性和方法,不能繼承原型鏈上的屬性和方法。
3:組合繼承通過調用父類構造,繼承父類的屬性并保留傳參的優點,然后通過將父類實例作為子類原型,實現函數復用。
保留了構造函數繼承與原型鏈繼承的優點。但是執行了兩次Person,屬性重復了。
function Person(name) { this.name = name; this.value = ["head", "body", "legs"]; } Person.prototype.getName = function() { return this.name; }; // 構造函數繼承 function Teacher(name, school){ // 執行又一次Person Person.call(this, name); this.school = school; } // 原型鏈繼承 // 執行一次Person Teacher.prototype = new Person(); const Eric = new Teacher("Eric",27); Eric.getName(); // 輸出:Eric // prototype構造器指回自己 Teacher.prototype.constructor = Teacher; Teacher.prototype.getSchool = function() { return this.school; };
特點:既可以繼承實例屬性和方法,也可以繼承原型屬性和方法。既是子類的實例也是父類的實例,不存在引用屬性共享的問題。可以傳參,函數可復用。
缺點:調用兩次父類構造函數,生成了兩份實例。
4:原型式繼承借助原型可以基于已有的對象創建新的對象,同時還不必因此創建自定義類型。
原理:(本質)利用一個空對象作為一個中介。
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()原理:用一個函數包裝一個對象,然后返回這個函數的調用,這個函數就變成了一個可以隨意添增屬性的實例或對象。
Object.prototype.create = function(obj) { function Fun() {} Fun.prototype = obj; return new Fun(); }
缺點有兩點:第一點是無法傳遞參數,第二點是引用類型存在變量的污染。
5:寄生式繼承寄生式繼承的思路與寄生構造函數和工廠模式類似,即創建一個僅用于封裝繼承過程的函數。
目的:在原型式繼承的基礎上,寄生增加了一些新的方法和屬性。
它的特點同原型式繼承一樣,也是無法傳遞參數,而且引用的數據類型也容易存在樣式污染。
Object.createNew()
Object.prototype.createNew = function(obj){ var newObj = Object.create(obj); //獲取長度等于一個function newObj.getLength = function(){ ... }; return newObj; }6:寄生組合繼承
目的:為了解決數據重復拷貝兩遍的問題。
Super只執行一次。
//定義Super構造函數 function Super(name) { this.name = name; this.value = ["Hello", "Word"]; } //在super的原型鏈添加一個getName Super.prototype.getName = function() { return this.name; }; //定義Sub function Sub(name, age) { //調用構造函數繼承 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:繼承多個對象
借助原型式繼承Object.create拿到SuperClass,也就是父類,拿到父類的prototype之后把它賦給ClassOne,再然后我們將ClassTwo的prototype使用一個Object.assign,一個對象的拷貝,把它拷貝到ClassOne里面來,然后最后ClassOne.prototype.constructor等于ClassOne。
也就是使用一個Class.assign把所有我們想要繼承的父類的prototype全部組合到一起完成一個拷貝,之后再賦給對象。
function ClassOne.prototype = Object.create(SuperClass.prototype); Object.assign(ClassOne.prototype, ClassTwo.prototype); ClassOne.prototype.constructor = ClassOne;
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/105852.html
摘要:特點跟借用構造函數模式一樣,每次創建對象都會創建一遍方法。缺點寄生組合式繼承使用時說明解決了組合繼承存在的問題特點只調用了一次構造函數,并且因此避免了在上面創建不必要的多余的屬性原型鏈還能保持不變還能夠正常使用和缺點參考資料 原型鏈繼承 //父類 function Person(name, age) { this.name = name; this.age = age; ...
摘要:可以通過構造函數和原型的方式模擬實現類的功能。原型式繼承與類式繼承類式繼承是在子類型構造函數的內部調用超類型的構造函數。寄生式繼承這種繼承方式是把原型式工廠模式結合起來,目的是為了封裝創建的過程。 js繼承的概念 js里常用的如下兩種繼承方式: 原型鏈繼承(對象間的繼承) 類式繼承(構造函數間的繼承) 由于js不像java那樣是真正面向對象的語言,js是基于對象的,它沒有類的概念。...
摘要:原型繼承與類繼承類繼承是在子類型構造函數的內部調用父類型的構造函數原型式繼承是借助已有的對象創建新的對象,將子類的原型指向父類。 JavaScript 繼承方式的概念 js 中實現繼承有兩種常用方式: 原型鏈繼承(對象間的繼承) 類式繼承(構造函數間的繼承) JavaScript不是真正的面向對象的語言,想實現繼承可以用JS的原型prototype機制或者call和apply方法 在面...
摘要:原型式繼承利用一個空對象作為中介,將某個對象直接賦值給空對象構造函數的原型。其中表示構造函數,一個類中只能有一個構造函數,有多個會報出錯誤如果沒有顯式指定構造方法,則會添加默認的方法,使用例子如下。 (關注福利,關注本公眾號回復[資料]領取優質前端視頻,包括Vue、React、Node源碼和實戰、面試指導)showImg(https://segmentfault.com/img/rem...
摘要:可以看出,這個查找過程是一個鏈式的查找,每個對象都有一個到它自身原型對象的鏈接,這些鏈接組件的整個鏈條就是原型鏈。原型的構建字面量方式當通過字面量方式創建對象時,它的原型就是。 面向對象 JavaScript沒有類(class)的概念的(ES6 中的class也只不過是語法糖,并非真正意義上的類),而在JavaScript中,在 JavaScript 中,除了 String, Numb...
閱讀 2721·2021-11-22 13:54
閱讀 1062·2021-10-14 09:48
閱讀 2291·2021-09-08 09:35
閱讀 1549·2019-08-30 15:53
閱讀 1166·2019-08-30 13:14
閱讀 605·2019-08-30 13:09
閱讀 2520·2019-08-30 10:57
閱讀 3333·2019-08-29 13:18