自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

聊一聊 JavaScript 中的 Super() 是什么?

開發(fā) 前端
本文將假定您至少對構(gòu)造函數(shù)以及子類和父類的概念有所了解。如果你不了解這些,則可能需要從Mozilla的Object-oriented JavaScript for beginners開始學(xué)習(xí)。

當(dāng)你在js代碼中看到有調(diào)用super()時(shí),會(huì)不會(huì)好奇這個(gè)super()到底有什么作用?在子類中,您可以使用super()調(diào)用其父級的構(gòu)造函數(shù),并使用super.<方法名>來訪問其父級的方法。

本文將假定您至少對構(gòu)造函數(shù)以及子類和父類的概念有所了解。如果你不了解這些,則可能需要從Mozilla的Object-oriented JavaScript for beginners開始學(xué)習(xí)。

super并不是只javascript語言才有--許多其它編程語言,如java, python都有一個(gè)super()關(guān)鍵字來提供對父類的引用。與Java和Python不同,JavaScript并不是圍繞類繼承模型構(gòu)建的。相反,它擴(kuò)展了JavaScript的原型繼承模型,以提供與類繼承一致的行為。

讓我們進(jìn)一步了解它,并查看一些代碼示例。

首先,這里引用的一段話Mozilla’s web docs for classes:

JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical sugar over JavaScript’s existing prototype-based inheritance. The class syntax does not introduce a new object-oriented inheritance model to JavaScript.

一個(gè)簡單的子類和父類的例子將有助于說明這句話的真正含義:

class Fish {
constructor(habitat, length) {
this.habitat = habitat
this.length = length
}
renderProperties(element) {
element.innerHTML = JSON.stringify(this)
}
}
class Trout extends Fish {
constructor(habitat, length, variety) {
super(habitat, length)
this.variety = variety
}
renderPropertiesWithSuper(element) {
element.className="green"
super.renderProperties(element);
}
}
let grouper = new Fish("saltwater", "26in");
console.log(grouper);
grouper.renderProperties(document.getElementById("grouper"));
let rainbowTrout = new Trout("freshwater", "14in", "rainbow");
console.log(rainbowTrout);
//invoke function from parent prototype
rainbowTrout.renderProperties(document.getElementById("rainbowTrout"));
//invoke function from child's prototype
rainbowTrout.renderPropertiesWithSuper(document.getElementById("rainbowTroutParent"));

我的例子有兩個(gè)類:Fish和 Trout。所有的魚都有棲息地和長度的信息,所以這些屬性屬于魚類。鱒魚也有一個(gè)多樣性的屬性,所以它基于fish又?jǐn)U展了屬性variety。下面是魚和鱒魚的構(gòu)造函數(shù):

class fish {
constructor(habitat, length) {
this.habitat = habitat
this.length = length
}
}
class trout extends fish {
constructor(habitat, length, variety) {
super(habitat, length)
this.variety = variety
}
}

魚類的構(gòu)造函數(shù)定義棲息地和長度,鱒魚的構(gòu)造函數(shù)定義了種類。我必須在鱒魚的構(gòu)造函數(shù)中調(diào)用super(),否則在嘗試設(shè)置this.variety時(shí)會(huì)出現(xiàn)錯(cuò)誤。那是因?yàn)樵邝V魚類的第一行中,我告訴JavaScript鱒魚是使用extends關(guān)鍵字的“魚”。

這意味著鱒魚的上下文包括fish類中定義的屬性和方法,以及鱒魚為其自身定義的任何屬性和方法。調(diào)用super()本質(zhì)上使JavaScript知道魚是什么,以便可以為鱒魚創(chuàng)建this上下文,其中包括魚中的所有內(nèi)容以及我們將為鱒魚定義的所有內(nèi)容。fish類不需要super(),因?yàn)樗摹案讣墶敝皇荍avaScript對象。Fish已處于原型繼承鏈的頂部,因此無需調(diào)用super()。

我在trout的構(gòu)造函數(shù)中調(diào)用super(habitat, length),使這三個(gè)屬性在這個(gè)上下文中立即可用。實(shí)際上還有另一種方法可以從trout的構(gòu)造函數(shù)中得到相同的行為。我必須調(diào)用super()來避免引用錯(cuò)誤,但我不必使用fish的構(gòu)造函數(shù)所期望的參數(shù)正確調(diào)用它。

這是因?yàn)槲也恍枰褂胹uper()來給fish創(chuàng)建的字段賦值,我只需要確保這些字段存在于這個(gè)上下文上。這是JavaScript與真正的類繼承模型(例如Java)之間的重要區(qū)別,根據(jù)我的實(shí)現(xiàn)方式,以下代碼可能是非法的:

class trout extends fish {
constructor(habitat, length, variety) {
super()
this.habitat = habitat
this.length = length
this.variety = variety
}
}

這種替代的trout構(gòu)造函數(shù)使您更難分辨哪些屬性屬于fish和哪些屬性屬于trout,但其結(jié)果與前面的示例相同。唯一的區(qū)別是,在此情況下,不帶參數(shù)調(diào)用super()會(huì)在當(dāng)前此this的上下文上創(chuàng)建屬性habitat和length,而無需為其分配任何內(nèi)容。

如果我在第三行之后調(diào)用console.log(this),它將顯示{habitat:undefined,length:undefined}。第四行和第五行分配值。

我也可以在trout的構(gòu)造函數(shù)之外使用super(),以引用父類上的方法。在這里,我定義了renderProperties方法,該方法會(huì)將類的所有屬性顯示在我傳遞給它的HTML元素中。

super()在這里很有用,因?yàn)槲蚁M业膖rout類實(shí)現(xiàn)一個(gè)類似的方法,該方法可以完成相同的工作,并且還要多做一些事情—它在更新HTML之前為該元素執(zhí)定了一個(gè)類名。我可以通過在相關(guān)類函數(shù)內(nèi)調(diào)用super.renderProperties()來重用fish類中的邏輯。

class fish {
renderProperties(element) {
element.innerHTML = JSON.stringify(this)
}
}
class trout extends fish {
renderPropertiesWithSuper(element) {
element.className="green"
super.renderProperties(element);
}
}

你在定義時(shí)方法命名很重要。我把我在trout類中的方法叫做renderPropertiesWithSuper(),因?yàn)槲胰匀幌M梢赃x擇調(diào)用trout.renderProperties(),因?yàn)樗窃趂ish類上定義的。

如果我只是將函數(shù)命名為trout類中的renderProperties,那將是完全有效的;但是,我將不再能夠從trout的實(shí)例中直接訪問這兩個(gè)函數(shù)--調(diào)用trout.renderProperties將調(diào)用定義在trout上的函數(shù)。

這不一定是一個(gè)有用的實(shí)現(xiàn)方式--可以說,像這樣調(diào)用super的函數(shù)覆蓋其父函數(shù)的名稱是一個(gè)更好的模式--但它確實(shí)說明了JavaScript允許你的類是多么靈活。

其實(shí)也可以完全可以不使用前面代碼示例中非常有用的super()或extends關(guān)鍵字來實(shí)現(xiàn)這個(gè)例子,只是不太方便。這就是Mozilla所說的 "語法糖 "的意思。事實(shí)上,如果我把我之前的代碼插入像Babel這樣的移植器中,以確保我的類能與舊版本的JavaScript一起工作,它將生成一些更接近下面的代碼。

這里的代碼大部分是一樣的,但你會(huì)注意到,如果沒有extends和super(),我必須將fish和trout定義為函數(shù)并直接訪問它們的原型。我還必須在第15、16和17行對原型做一些額外的改動(dòng),并確保trout可以在其構(gòu)造函數(shù)中傳遞正確的this上下文(混合繼承)。

如果你有興趣深入了解這里發(fā)生的事情,Eric Green有一篇優(yōu)秀的帖子,里面有很多代碼片段,介紹了如何使用和不使用ES2015構(gòu)建類以及其繼承的關(guān)系。

function Fish(habitat, length) {
this.habitat = habitat;
this.length = length;
}
Fish.prototype.renderProperties = function(element) {
element.innerHTML = JSON.stringify(this)
};
function Trout(habitat, length, variety) {
this._super.call(this, habitat, length);
this.variety = variety;
}
Trout.prototype = Object.create(Fish.prototype);
Trout.prototype.constructor = Trout;
Trout.prototype._super = Fish;
Trout.prototype.renderPropertiesWithSuper = function(element) {
element.className="green";
this.renderProperties(element);
};
let grouper = new Fish("saltwater", "26in");
grouper.renderProperties(document.getElementById("grouper"));
var rainbowTrout = new Trout("freshwater", "14in", "rainbow");
//invoke function from parent
rainbowTrout.renderProperties(document.getElementById("rainbowTrout"));
//invoke function from child
rainbowTrout.renderPropertiesWithSuper(document.getElementById("rainbowTroutParent"));

JavaScript中的類是共享功能的強(qiáng)大方法。例如,React中的類組件依賴于它們。但是,如果您習(xí)慣使用另一種使用類繼承模型的語言進(jìn)行面向?qū)ο蟮木幊蹋敲碕avaScript的行為有時(shí)可能會(huì)令人驚訝。所以學(xué)習(xí)原型繼承的基礎(chǔ)知識(shí)可以幫助闡明如何使用JavaScript中的類。

責(zé)任編輯:姜華 來源: 新鈦云服
相關(guān)推薦

2019-12-02 16:23:03

Python編程語言“垃圾”回收

2022-08-30 07:39:57

C++namespace隔離

2020-12-11 11:11:44

原子類JavaCAS

2021-01-04 08:09:07

Linux內(nèi)核Watchdog

2021-12-29 07:18:20

重構(gòu)工具資源

2022-03-06 20:35:41

并發(fā)串行CAP

2024-10-16 15:11:58

消息隊(duì)列系統(tǒng)設(shè)計(jì)

2022-01-11 15:44:15

JavaScript圖表庫數(shù)據(jù)

2024-01-02 13:26:39

TLSC#線程

2023-07-06 13:56:14

微軟Skype

2021-06-30 07:19:35

微服務(wù)業(yè)務(wù)MySQL

2019-12-12 14:52:10

數(shù)據(jù)庫腳本

2020-09-08 06:54:29

Java Gradle語言

2023-09-22 17:36:37

2021-01-28 22:31:33

分組密碼算法

2020-05-22 08:16:07

PONGPONXG-PON

2018-07-23 15:28:29

HTTPCookieHeader

2024-03-28 09:02:25

PythonGetattr工具

2021-08-01 09:55:57

Netty時(shí)間輪中間件

2023-09-27 16:39:38

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)