搜尋
首頁web前端js教程JavaScript中關於繼承的六種實作方式

JavaScript中關於繼承的六種實作方式

Oct 23, 2017 am 09:44 AM
javascriptjs方式

javascript 中關於繼承的描述:

            許多物件導向語言支援兩種繼承的方式:介面繼承與實作繼承。介面繼承只繼承方法簽名,而實作繼承則繼承實際的方法。在 javascript 中由於函數沒有簽章也就無法實作介面繼承,而只支援實作繼承,而且實作繼承主要透過原型鏈來實現的。

            先引用下官方文件對原型鏈的描述:其基本想法是利用原型讓一個引用型別繼承另一個引用型別的屬性與方法。要理解這個概念要先弄清楚建構函數,原型,和實例的關係:每個建構函數(只要是函數)都有一個prototype 屬性該屬性指向一個物件(這個物件就是建構函數的原型物件);原型物件(只要是物件)中都有一個constructor 屬性該屬性指向一個建構子;而實例中都包含一個指向原型物件的內部指標[[Prototype]]。說白了就是原型鏈的建構是透過將一個類型的實例賦值給另一個建構函數的原型來實現的。這樣子類型就可以存取定義在超類型上的所有屬性和方法了。每個對像都有自己的原型對象,以原型對象為模板從原型對象繼承屬性和方法,原型對像也可以有自己的原型並從中繼承屬性和方法,一層一層,以此類推,這種關係被稱為原型鏈它解釋了為何一個物件會擁有定義在其他物件上的屬性和方法。


javascript 中實作繼承的六種方式:

            1、原型鏈

            2、使用建構子
## )


            4、原型式繼承


        

#       
            6、寄生組合式繼承(使用組合繼承與寄生式繼承)

1、原型鏈

#

// 实现原型链的一种基本模式
function SuperType(){
            this.property = true;
}
SuperType.prototype.getSuperValue = function(){
            return this.property;
};
function SubType(){
            this.subproperty = false;
}

// 继承,用 SuperType 类型的一个实例来重写 SubType 类型的原型对象
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function(){
            return this.subproperty;
};
var instance = new SubType();
alert(instance.getSuperValue());     // true

PS:SubType 繼承了 SuperType,而繼承是透過創建 SuperType 的實例,並將該實例賦值給 SubType 的原型實現的。實現的本質是重寫子類型的原型對象,並以一個新類型的實例取代。子類型的新原型物件中有一個內部屬性 [[Prototype]] 指向了 SuperType 的原型,還有一個從 SuperType 原型繼承過來的屬性 constructor 指向了 SuperType 建構子。最終的原型鍊是這樣的:instance 指向SubType 的原型,SubType 的原型又指向SuperType 的原型,SuperType 的原型又指向Object 的原型(所有函數的預設原型都是Object 的實例,因此預設原型都會包含一個內部指針,指向Object.prototype)。
原型鏈的缺點:
           1、透過原型來實現繼承時,原型實際上會變成另一個類型的實例。於是,原先的實例屬性也就順理成章地變成了現在的原型屬性,並且會被所有的實例共享。這樣理解:在超型別建構函式中定義的參考型別值的實例屬性,會在子型別原型上變成原型屬性被所有子型別實例所共用。
           2、建立子類型的實例時,無法傳遞參數給超類型的建構子。

2、借用建構子(也稱為偽造物件或經典繼承)

// 在子类型构造函数的内部调用超类型构造函数;使用 apply() 或 call() 方法将父对象的构造函数绑定在子对象上
function SuperType(){
            // 定义引用类型值属性
            this.colors = ["red","green","blue"];
}
function SubType(){
            // 继承 SuperType,在这里还可以给超类型构造函数传参
            SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push("purple");
alert(instance1.colors);     // "red,green,blue,purple"

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

PS:透過使用apply() 或call() 方法,我們實際上是在將要創建的SubType 實例的環境下呼叫了SuperType 建構子。這樣一來,就會在新 SubType 物件上執行 SuperType() 函數中定義的所有物件初始化程式碼。結果 SubType 的每個實例都會有自己的 colors 屬性的副本了。
借用建構函式的優點是解決了原型鏈實作繼承存在的兩個問題;借用建構函式的缺點是方法都在建構函式中定義,因此函式復用就無法實作了。而且,在超類型的原型中定義的方法,對子類型而言也是不可見的,結果所有型別都只能使用建構函式模式。

3、組合繼承(也稱偽經典繼承)

// 将原型链和借用构造函数的技术组合到一块。使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。
这样,既通过在原型上定义方法实现了函数复用,又能够保证每个实例都有自己的属性。
function SuperType(name){
            this.name = name;
            this.colors = ["red","green","blue"];
}
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 instance1 = new SubType("luochen",22);
instance1.colors.push("purple");
alert(instance1.colors);      // "red,green,blue,purple"
instance1.sayName();
instance1.sayAge();

var instance2 = new SubType("tom",34);
alert(instance2.colors);      // "red,green,blue"
instance2.sayName();
instance2.sayAge();

PS:組合繼承避免了原型鍊和借用建構函式的缺陷,融合了它們的優點,成為javascript 中最常用的繼承模式。而且,使用 instanceof 運算子和 isPrototype() 方法也能夠用於識別基於組合繼承所建立的物件。但是,它也有自己的不足。最大的問題是無論在什麼情況下,都會呼叫兩次超類型建構函數:一次是在建立子類型原型的時候,另一次是在子類型建構函式內部。

4、原型式繼承

// 借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。
1、自定义一个函数来实现原型式继承
function object(o){
            function F(){}
            F.prototype = o;
            return new F();
}

PS:在object() 函數內部,先建立一個臨時性的建構函數,然後將傳入的物件當作這個建構函數的原型,最後傳回這個臨時型別的一個新實例。實質上,object() 對傳入其中的物件執行了一次淺複製。
2、使用 Object.create() 方法實作原型式繼承。這個方法接收兩個參數:一是用作新物件原型的物件和一個為新物件定義額外屬性的物件。在傳入一個參數的情況下,此方法與 object() 方法作用一致。
在傳入第二個參數的情況下,指定的任何屬性都會覆寫原型物件上的同名屬性。

var person = {
            name: "luochen",
            colors: ["red","green","blue"]
}; 
var anotherPerson1 = Object.create(person,{
            name: {
                    value: "tom"
            }
});
var anotherPerson2 = Object.create(person,{
            name: {
                    value: "jerry"
            }
});
anotherPerson1.colors.push("purple");
alert(anotherPerson1.name);     // "tom"
alert(anotherPerson2.name);     // "jerry"
alert(anotherPerson1.colors);    // "red,green,blue,purple"
alert(anotherPerson2.colors);    // "red,green,bule,purple";

PS:只是想讓一個物件與另一個物件類似的情況下,原型式繼承是完全可以勝任的。但是缺點是:包含引用類型值的屬性總是會共用對應的值。

5、寄生式繼承

// 创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后返回这个对象
function createPerson(original){
            var clone = Object.create(original);   // 通过 Object.create() 函数创建一个新对象
            clone.sayGood = function(){              // 增强这个对象
                        alert("hello world!!!");
            };
            return clone;                                      // 返回这个对象 
}

PS:在主要考慮物件而不是自訂類型和建構函數的情況下,寄生式繼承也是一個有用的模式。此模式的缺點是做不到函數重複使用。

6、寄生組合式繼承

// 通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型
function SuperType(name){
            this.name = name;
            this.colors = ["red","green","blue"];
}
SuperType.prototype.sayName = function(){
            alert(this.name);
};
function SubType(name,age){
            SuperType.call(this,name);
            this.age = age;
}
// 创建超类型原型的一个副本
var anotherPrototype = Object.create(SuperType.prototype);
// 重设因重写原型而失去的默认的 constructor 属性
anotherPrototype.constructor = SubType;
// 将新创建的对象赋值给子类型的原型
SubType.prototype = anotherPrototype;

SubType.prototype.sayAge = function(){
            alert(this.age);
};
var instance1 = new SubType("luochen",22);
instance1.colors.push("purple");
alert(instance1.colors);      // "red,green,blue,purple"
instance1.sayName();
instance1.sayAge();

var instance2 = new SubType("tom",34);
alert(instance2.colors);      // "red,green,blue"
instance2.sayName();
instance2.sayAge();

PS:這個範例的高效率體現在它只呼叫一次SuperType 建構函數,並且因此避免了在SubType.prototype 上面建立不必要,多餘的屬性。同時,原型鏈還能維持不變;因此也能夠正常使用 instance 運算元和 isPrototype() 方法。

以上是JavaScript中關於繼承的六種實作方式的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
JavaScript應用程序:從前端到後端JavaScript應用程序:從前端到後端May 04, 2025 am 12:12 AM

JavaScript可用於前端和後端開發。前端通過DOM操作增強用戶體驗,後端通過Node.js處理服務器任務。 1.前端示例:改變網頁文本內容。 2.後端示例:創建Node.js服務器。

Python vs. JavaScript:您應該學到哪種語言?Python vs. JavaScript:您應該學到哪種語言?May 03, 2025 am 12:10 AM

選擇Python還是JavaScript應基於職業發展、學習曲線和生態系統:1)職業發展:Python適合數據科學和後端開發,JavaScript適合前端和全棧開發。 2)學習曲線:Python語法簡潔,適合初學者;JavaScript語法靈活。 3)生態系統:Python有豐富的科學計算庫,JavaScript有強大的前端框架。

JavaScript框架:為現代網絡開發提供動力JavaScript框架:為現代網絡開發提供動力May 02, 2025 am 12:04 AM

JavaScript框架的強大之處在於簡化開發、提升用戶體驗和應用性能。選擇框架時應考慮:1.項目規模和復雜度,2.團隊經驗,3.生態系統和社區支持。

JavaScript,C和瀏覽器之間的關係JavaScript,C和瀏覽器之間的關係May 01, 2025 am 12:06 AM

引言我知道你可能會覺得奇怪,JavaScript、C 和瀏覽器之間到底有什麼關係?它們之間看似毫無關聯,但實際上,它們在現代網絡開發中扮演著非常重要的角色。今天我們就來深入探討一下這三者之間的緊密聯繫。通過這篇文章,你將了解到JavaScript如何在瀏覽器中運行,C 在瀏覽器引擎中的作用,以及它們如何共同推動網頁的渲染和交互。 JavaScript與瀏覽器的關係我們都知道,JavaScript是前端開發的核心語言,它直接在瀏覽器中運行,讓網頁變得生動有趣。你是否曾經想過,為什麼JavaScr

node.js流帶打字稿node.js流帶打字稿Apr 30, 2025 am 08:22 AM

Node.js擅長於高效I/O,這在很大程度上要歸功於流。 流媒體匯總處理數據,避免內存過載 - 大型文件,網絡任務和實時應用程序的理想。將流與打字稿的類型安全結合起來創建POWE

Python vs. JavaScript:性能和效率注意事項Python vs. JavaScript:性能和效率注意事項Apr 30, 2025 am 12:08 AM

Python和JavaScript在性能和效率方面的差異主要體現在:1)Python作為解釋型語言,運行速度較慢,但開發效率高,適合快速原型開發;2)JavaScript在瀏覽器中受限於單線程,但在Node.js中可利用多線程和異步I/O提升性能,兩者在實際項目中各有優勢。

JavaScript的起源:探索其實施語言JavaScript的起源:探索其實施語言Apr 29, 2025 am 12:51 AM

JavaScript起源於1995年,由布蘭登·艾克創造,實現語言為C語言。 1.C語言為JavaScript提供了高性能和系統級編程能力。 2.JavaScript的內存管理和性能優化依賴於C語言。 3.C語言的跨平台特性幫助JavaScript在不同操作系統上高效運行。

幕後:什麼語言能力JavaScript?幕後:什麼語言能力JavaScript?Apr 28, 2025 am 12:01 AM

JavaScript在瀏覽器和Node.js環境中運行,依賴JavaScript引擎解析和執行代碼。 1)解析階段生成抽象語法樹(AST);2)編譯階段將AST轉換為字節碼或機器碼;3)執行階段執行編譯後的代碼。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。