JavaScript中super关键词的必要性
super关键词
JS中super关键词是用来调用原型对象的属性和方法的,本文分析使用super关键词的必要性
this指向导致的原型调用问题
JS中存在多种”this绑定“方式,最核心的就是”调用绑定“,即xxx.show()
,那么show方法中的this就指向xxx。
如果直接show(),那么实际上在浏览器中是window.show(),this就指向window。
通常this绑定在基于原型链的方法调用下是没有问题的,无论调用的方法是否来自于原型。
但是,在继承的场景下,如果需要手动调用原型方法,比如this.__proto__.show()
,那么show方法中的this就会指向this.proto,即原型对象自己。
const person = {
name: "person.name",
show() {
console.log(this.name);
},
};
const user = {
__proto__: person,
name: "user.name",
show() {
// person.name 由于此时原型对象中的this是原型自己(this.__proto__)
this.__proto__.show();
},
};
user.show();
这里就会产生冲突,因为我们希望即便手动调用原型,this的指向仍然是对象本身而不是原型。
super关键字就可以解决这种问题,既可以调用原型方法同时又不改变this指向。
通过call方法解决this指向问题
当然我们可以使用call方法重新定义this指向。
const person = {
name: "person.name",
show() {
console.log(this.name);
},
};
const user = {
__proto__: person,
name: "user.name",
show() {
// 使用call方法重新定义this指向
this.__proto__.show.call(this)
},
};
user.show();
但是this.__proto__.show.call()
在多级继承中就不生效了。
const person = {
name: "person.name",
show() {
console.log(this.name);
},
};
const user = {
__proto__: person,
name: "user.name",
show() {
// 多级继承时,由于this始终指向admin,则this.__proto__指向user而不是person
// this.__proto__.show.call(this)
// 当然可以为了admin.show()手动调整,但显然这样做的适应性很差
// 如果user.show()则会报错
// this.__proto__.__proto__.show.call(this)
},
};
const admin = {
__proto__: user,
name: "admin.name",
show() {
this.__proto__.show.call(this)
}
}
admin.show();
所以,手动修改this的指向既繁琐又不灵活,JS于是提供了super关键词实现这些功能。