网易首页 > 网易号 > 正文 申请入驻

JavaScript中的 super() 是什么?

0
分享至

新钛云服已累计为您分享701篇技术干货

当你在js代码中看到有调用super()时,会不会好奇这个super()到底有什么作用?在子类中,您可以使用super()调用其父级的构造函数,并使用super.<方法名>来访问其父级的方法。

本文将假定您至少对构造函数以及子类和父类的概念有所了解。如果你不了解这些,则可能需要从Mozilla的 Object-oriented JavaScript for beginners 开始学习。

super并不是只javascript语言才有--许多其它编程语言,如java, python都有一个super()关键字来提供对父类的引用。与Java和Python不同,JavaScript并不是围绕类继承模型构建的。相反,它扩展了JavaScript的原型继承模型,以提供与类继承一致的行为。

让我们进一步了解它,并查看一些代码示例。

首先,这里引用的一段话 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.

一个简单的子类和父类的例子将有助于说明这句话的真正含义:


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"));

我的例子有两个类:Fish和 Trout。所有的鱼都有栖息地和长度的信息,所以这些属性属于鱼类。鳟鱼也有一个多样性的属性,所以它基于fish又扩展了属性variety。下面是鱼和鳟鱼的构造函数:


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
}
}

鱼类的构造函数定义栖息地和长度,鳟鱼的构造函数定义了种类。我必须在鳟鱼的构造函数中调用super(),否则在尝试设置this.variety时会出现错误。那是因为在鳟鱼类的第一行中,我告诉JavaScript鳟鱼是使用extends关键字的“鱼”。

这意味着鳟鱼的上下文包括fish类中定义的属性和方法,以及鳟鱼为其自身定义的任何属性和方法。调用super()本质上使JavaScript知道鱼是什么,以便可以为鳟鱼创建this上下文,其中包括鱼中的所有内容以及我们将为鳟鱼定义的所有内容。fish类不需要super(),因为它的“父级”只是JavaScript对象。Fish已处于原型继承链的顶部,因此无需调用super()。

我在trout的构造函数中调用super(habitat, length),使这三个属性在这个上下文中立即可用。实际上还有另一种方法可以从trout的构造函数中得到相同的行为。我必须调用super()来避免引用错误,但我不必使用fish的构造函数所期望的参数正确调用它。

这是因为我不需要使用super()来给fish创建的字段赋值,我只需要确保这些字段存在于这个上下文上。这是JavaScript与真正的类继承模型(例如Java)之间的重要区别,根据我的实现方式,以下代码可能是非法的:


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


这种替代的trout构造函数使您更难分辨哪些属性属于fish和哪些属性属于trout,但其结果与前面的示例相同。唯一的区别是,在此情况下,不带参数调用super()会在当前此this的上下文上创建属性habitat和length,而无需为其分配任何内容。

如果我在第三行之后调用console.log(this),它将显示{habitat:undefined,length:undefined}。第四行和第五行分配值。

我也可以在trout的构造函数之外使用super(),以引用父类上的方法。在这里,我定义了renderProperties方法,该方法会将类的所有属性显示在我传递给它的HTML元素中。

super()在这里很有用,因为我希望我的trout类实现一个类似的方法,该方法可以完成相同的工作,并且还要多做一些事情—它在更新HTML之前为该元素执定了一个类名。我可以通过在相关类函数内调用super.renderProperties()来重用fish类中的逻辑。


class fish {
renderProperties(element) {
element.innerHTML = JSON.stringify(this)

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

你在定义时方法命名很重要。我把我在trout类中的方法叫做renderPropertiesWithSuper(),因为我仍然希望可以选择调用trout.renderProperties(),因为它是在fish类上定义的。

如果我只是将函数命名为trout类中的renderProperties,那将是完全有效的;但是,我将不再能够从trout的实例中直接访问这两个函数--调用trout.renderProperties将调用定义在trout上的函数。

这不一定是一个有用的实现方式--可以说,像这样调用super的函数覆盖其父函数的名称是一个更好的模式--但它确实说明了JavaScript允许你的类是多么灵活。

其实也可以完全可以不使用前面代码示例中非常有用的super()或extends关键字来实现这个例子,只是不太方便。这就是Mozilla所说的 "语法糖 "的意思。事实上,如果我把我之前的代码插入像Babel这样的移植器中,以确保我的类能与旧版本的JavaScript一起工作,它将生成一些更接近下面的代码。

这里的代码大部分是一样的,但你会注意到,如果没有extends和super(),我必须将fish和trout定义为函数并直接访问它们的原型。我还必须在第15、16和17行对原型做一些额外的改动,并确保trout可以在其构造函数中传递正确的this上下文(混合继承)。

如果你有兴趣深入了解这里发生的事情,Eric Green有一篇优秀的帖子,里面有很多代码片段,介绍了如何使用和不使用ES2015构建类以及其继承的关系。


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中的类是共享功能的强大方法。例如,React中的类组件依赖于它们。但是,如果您习惯使用另一种使用类继承模型的语言进行面向对象的编程,那么JavaScript的行为有时可能会令人惊讶。所以学习原型继承的基础知识可以帮助阐明如何使用JavaScript中的类。

*原文链接:https://css-tricks.com/what-is-super-in-javascript/

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
40集《蜜语纪》大结局!许蜜语求婚当晚,纪封终于说出了那个秘密

40集《蜜语纪》大结局!许蜜语求婚当晚,纪封终于说出了那个秘密

小猫追剧
2026-04-29 13:05:14
退法网或再退温网!阿尔卡拉斯会是下一个德尔波特罗吗?

退法网或再退温网!阿尔卡拉斯会是下一个德尔波特罗吗?

网球之家
2026-04-29 08:26:43
余承东再次向奇瑞董事长,正式道歉

余承东再次向奇瑞董事长,正式道歉

小李车评李建红
2026-04-29 08:00:03
你的Fire TV Stick快"过期"了,亚马逊给出最后期限

你的Fire TV Stick快"过期"了,亚马逊给出最后期限

薛定谔的BUG
2026-04-28 21:14:00
北京车展:售价718万元,红旗金葵花国礼亮相,竞争劳斯莱斯幻影

北京车展:售价718万元,红旗金葵花国礼亮相,竞争劳斯莱斯幻影

沙雕小琳琳
2026-04-30 01:59:45
六台主持人:皇马新任主帅的最终候选人是穆里尼奥和克洛普

六台主持人:皇马新任主帅的最终候选人是穆里尼奥和克洛普

懂球帝
2026-04-30 02:38:05
雅迪、爱玛、九号等8家电动车企业被约谈,北京严打电动自行车超标改装

雅迪、爱玛、九号等8家电动车企业被约谈,北京严打电动自行车超标改装

红星新闻
2026-04-29 18:39:18
中国羽毛球协会官网删除张军信息,国羽官方账号清空张军新闻

中国羽毛球协会官网删除张军信息,国羽官方账号清空张军新闻

米修体育
2026-04-29 19:13:28
去银行注销银行卡,柜员问销卡还是销户?一字之差后果完全不一样

去银行注销银行卡,柜员问销卡还是销户?一字之差后果完全不一样

复转这些年
2026-04-16 12:15:01
父母一旦跨过80岁大关,无关孝顺与否,立刻抓紧办8件急事

父母一旦跨过80岁大关,无关孝顺与否,立刻抓紧办8件急事

辉哥说动漫
2026-04-27 13:00:49
韩印谈完大事,李在明归国就硬刚:要把驻韩美军全赶出去?

韩印谈完大事,李在明归国就硬刚:要把驻韩美军全赶出去?

近代风云传
2026-04-30 01:05:14
皇马帅位彻底遇冷!头号热门果断拒绝,世界级名帅主动自荐

皇马帅位彻底遇冷!头号热门果断拒绝,世界级名帅主动自荐

奶盖熊本熊
2026-04-30 04:52:18
新加坡外长通告全球:如果被迫选边站队,不选美国也不会选中国

新加坡外长通告全球:如果被迫选边站队,不选美国也不会选中国

人间无味啊
2026-04-30 02:49:47
豆包提前查到事业编成绩单,全网炸了!

豆包提前查到事业编成绩单,全网炸了!

互联网品牌官
2026-04-27 18:11:08
仅落后于梅西、阿圭罗,小蜘蛛跻身阿根廷球员欧冠射手榜前三

仅落后于梅西、阿圭罗,小蜘蛛跻身阿根廷球员欧冠射手榜前三

懂球帝
2026-04-30 05:05:35
中共江苏省委十四届十一次全会召开

中共江苏省委十四届十一次全会召开

无锡高新区在线
2026-04-29 22:03:41
特朗普现在情况不妙?有人发现鲁比奥和万斯,已经有了反水的迹象

特朗普现在情况不妙?有人发现鲁比奥和万斯,已经有了反水的迹象

观星赏月
2026-04-29 21:39:49
轰炸中,伊朗国宝来到中国

轰炸中,伊朗国宝来到中国

中国新闻周刊
2026-04-27 07:30:21
我卖掉房子把钱分给子女,小儿子抱着我痛哭。三天后大儿媳来电话

我卖掉房子把钱分给子女,小儿子抱着我痛哭。三天后大儿媳来电话

老红点评社
2026-04-29 17:07:09
意大利议会批准:捐赠航母

意大利议会批准:捐赠航母

环球时报国际
2026-04-30 00:20:31
2026-04-30 05:31:00
新钛云服
新钛云服
云管理服务专家
468文章数 30关注度
往期回顾 全部

科技要闻

今晨庭审纪实|马斯克当庭讲述OpenAI被偷走

头条要闻

伊朗提出先解除封锁 特朗普回应

头条要闻

伊朗提出先解除封锁 特朗普回应

体育要闻

一场九球狂欢,各路神仙批量下凡

娱乐要闻

马頔一句话,孙杨妈妈怒骂节目组2小时

财经要闻

苏州,率先进入牛市

汽车要闻

技术天花板再摸高 全能型的奕境X9首秀

态度原创

游戏
时尚
本地
公开课
军事航空

平等曹飞所有老玩家的危机合约,为何是二游高难玩法最高的山?

夏天穿维希格,原来这么好看

本地新闻

用青花瓷的方式,打开西溪湿地

公开课

李玫瑾:为什么性格比能力更重要?

军事要闻

美国参议院否决限制特朗普对古巴动武的决议

无障碍浏览 进入关怀版