1 ES6中的繼承
ES6使用class關鍵字定義類,使用extends關鍵字繼承類別。子類別的constructor建構方法中必須呼叫super方法來獲得父類別的」this「對象,呼叫super時可以向父建構子傳參。子類別可以透過super物件直接使用父類別的屬性和方法,也可以透過同名屬性或方法覆寫父類別中的定義。
class Father { constructor () { this.surname = '王' this.money = Infinity } sayName () { console.log(`My surname is ${this.surname}.`) } } class Son extends Father { constructor (firstname) { super() this.firstname = firstname } sayName () { console.log(`My name is ${super.surname}${this.firstname}.`) } sayMoney () { console.log(`I have ${this.money} money.`) } } let Sephirex = new Son('撕葱') Sephirex.sayName() Sephirex.sayMoney()
ES6中的類別和繼承本質上是使用prototype實作的語法糖,類別中定義的方法相當於在prototype上定義方法,constructor方法中定義屬性相當於建構子模式,super方法相當於在子類別中呼叫父類別的建構子。以下繼續討論ES5中繼承的實作。
2 原型鏈繼承
原型鏈繼承的基本模式,就是讓子類型的原型物件指向父類型的一個實例,然後再為其原型擴展方法。
function Person (name) { this.name = name this.likes = ['apple', 'orange'] } Person.prototype.sayName = function () { console.log(this.name) } function Worker () { this.job = 'worker' } Worker.prototype = new Person() Worker.prototype.sayJob = function () { console.log(this.job) } let Tom = new Worker() let Jerry = new Worker() Tom.likes.push('grape') console.log(Jerry.likes) // [ 'apple', 'orange', 'purple' ]
原理:之前的文章我們討論了__proto__和prototype。子類別的實例中有一個__proto__指針,指向其建構函數的原型物件。而子類別建構子的原型指向父類別的一個實例,父類別實例中的__proto__又指向了父類別建構子的原型......如此層層遞進,就構成了原型鏈。
要注意的是,即使父類別中引用類型的屬性是在建構函式中定義的,還是會被子類別實例共用。這是因為子類別建構子的原型其實是父類別的一個實例,於是父類別的實例屬性自然就變成子類別的原型屬性,而引用類型值的原型屬性會在實例之間共用。
原型鏈的另一個問題是,沒有辦法在不影響所有物件實例的情況下,給父類別的建構子傳遞參數。像上面的例子,用 Worker.prototype = new Person() 將子類別原型指向父類別實例的時候, 如果傳入了初始化參數,則所有子類別的實例name屬性都會是傳入的參數。如果這裡不傳參數,後邊也沒有的辦法為父類別建構子傳參了。因此很少單獨使用原型鏈繼承模式。
3 借用建構子
借用建構子可以解決引用型別屬性被分享的問題。所謂「借用」建構函數,就是在子類別建構子中呼叫父類別的建構子---別忘了函數中 this 的指向跟函數在哪裡定義無關,而只跟在哪裡呼叫有關。我們可以利用call或apply,在子類別實例上呼叫父類別的建構函數,以取得父類別的屬性和方法,類似ES6子類別建構子中呼叫super方法。
function Person (name) { this.name = name this.likes = ['apple', 'orange'] } function Worker (name) { Person.call(this, name) this.job = 'worker' } let Tom = new Worker('Tom') Tom.likes.push("grape") let Jerry = new Worker('Jerry') console.log(Tom.likes) // [ 'apple', 'orange', 'grape' ] console.log(Jerry.likes) // [ 'apple', 'orange' ]
單純使用建構子的問題在於函數無法重複使用,且子類別無法取得父類別prototype上的屬性與方法。
4 組合繼承
組合繼承借用建構子定義實例屬性,使用原型鏈共享方法。組合繼承將原型鏈模式和借用建構函式結合起來,從而發揮二者之長,彌補各自不足,是js中最常用的繼承模式。
function Person (name) { this.name = name this.likes = ['apple', 'orange'] } Person.prototype.sayName = function () { console.log(this.name) } function Worker (name, job) { Person.call(this, name) // 第二次调用 Person() this.job = job } Worker.prototype = new Person() // 第一次调用 Person() Worker.prototype.constructor = Worker Worker.prototype.sayJob = function () { console.log(this.job) } let Tom = new Worker('Tom', 'electrician') Tom.likes.push('grape') console.log(Tom.likes) // [ 'apple', 'orange', 'grape' ] Tom.sayName() // Tom Tom.sayJob() // electrician let Jerry = new Worker('Jerry', 'woodworker') console.log(Jerry.likes) // [ 'apple', 'orange' ] Jerry.sayName() // Jerry Jerry.sayJob() // woodworker
組合繼承也並非沒有缺點,那就是繼承過程會兩次呼叫父類別建構子。在第一次呼叫Person 建構函式時,Worker.prototype 會得到兩個屬性:name 和likes;當呼叫Worker 建構函式時,又會呼叫一次Person 建構函數,這次直接建立了實例屬性name 和likes ,覆寫了原型中的兩個同名屬性。
5 原型式繼承
如下的object函數是道格拉斯·克羅克福德在一篇文章中記錄的。在 object函數內部,先創建了一個臨時性的構造函數,然後將傳入的對像作為這個構造函數的原型,最後返回了這個臨時類型的一個新實例。從本質上講, object() 對傳入其中的物件執行了一次淺複製。這種繼承方式,相當於把父類型的屬性和方法複製一份給子類型,然後再為子類型加入各自的屬性和方法。
這種方式同樣會共享引用類型值的屬性。
function object(o){ function F(){} F.prototype = o; return new F(); } let Superhero = { name: 'Avenger', skills: [], sayName: function () { console.log(this.name) } } let IronMan = object(Superhero) IronMan.name = 'Tony Stark' IronMan.skills.push('fly') let CaptainAmerica = object(Superhero) CaptainAmerica.name = 'Steve Rogers' CaptainAmerica.skills.push('shield') IronMan.sayName() // Tony Stark console.log(IronMan.skills) // [ 'fly', 'shield' ]
ES5中以 Object.create() 方法規範化了原型式繼承。這個方法接收兩個參數:一個用作新物件原型的物件和(可選的)一個為新物件定義額外屬性的物件。在傳入一個參數的情況下,Object.create() 與 object() 方法的行為相同。 Object.create() 方法的第二個參數與 Object.defineProperties() 方法的第二個參數格式相同。
let CaptainAmerica = Object.create(Superhero, { name: { value: 'Steve Rogers', configurable: false } })
6 寄生式繼承
寄生式繼承很好理解,只是一個封裝了繼承過程的工廠函數。由於方法直接定義在物件上,寄生式繼承新增的方法不能重複使用。
function inherit(parent){ var clone = Object.create(parent) clone.name = 'hulk' clone.sayHi = function(){ console.log("hi") } return clone } let Hulk = inherit(Superhero) Hulk.sayName() // hulk Hulk.sayHi() // hi
7 寄生組合式繼承
前面提到組合繼承是js中最常用的繼承方式,但不足是會呼叫兩次父類別的建構子。寄生組合式繼承可以解決這個問題,並且被認為是包含引用類型值的物件最理想的繼承方式。
寄生組合式繼承的基本想法是,不必為了指定子類別的原型而呼叫父類別的建構函數,需要的只是父類別原型的一個副本而已。寄生組合式繼承就是藉用建構函式來繼承屬性,然後使用寄生式繼承來繼承父類別的原型。
function inheritPrototype(subType, superType){ var prototype = Object.create(superType.prototype) prototype.constructor = subType subType.prototype = prototype } function Person (name) { this.name = name this.likes = ['apple', 'orange'] } Person.prototype.sayName = function () { console.log(this.name) } function Worker (name, job) { Person.call(this, name) this.job = job } inheritPrototype(Worker, Person) Worker.prototype.sayJob = function () { console.log(this.job) }
以上是js中有哪些繼承方式?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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

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

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

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

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

Python和JavaScript的未來趨勢包括:1.Python將鞏固在科學計算和AI領域的地位,2.JavaScript將推動Web技術發展,3.跨平台開發將成為熱門,4.性能優化將是重點。兩者都將繼續在各自領域擴展應用場景,並在性能上有更多突破。

Python和JavaScript在開發環境上的選擇都很重要。 1)Python的開發環境包括PyCharm、JupyterNotebook和Anaconda,適合數據科學和快速原型開發。 2)JavaScript的開發環境包括Node.js、VSCode和Webpack,適用於前端和後端開發。根據項目需求選擇合適的工具可以提高開發效率和項目成功率。

是的,JavaScript的引擎核心是用C語言編寫的。 1)C語言提供了高效性能和底層控制,適合JavaScript引擎的開發。 2)以V8引擎為例,其核心用C 編寫,結合了C的效率和麵向對象特性。 3)JavaScript引擎的工作原理包括解析、編譯和執行,C語言在這些過程中發揮關鍵作用。


熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

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

熱門文章

熱工具

禪工作室 13.0.1
強大的PHP整合開發環境

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

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

WebStorm Mac版
好用的JavaScript開發工具

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器