为什么子类继承父类的时候,子类重写的普通函数不会覆盖父类的箭头函数?
如下面这段代码
class Animal {
sayName = () => {
console.log('I hate coding')
}
}
class Monkey extends Animal {
sayName() {
console.log('I love coding');
}
}
const monkey = new Monkey();
monkey.sayName();
为什么输出会是I hate coding
,但是如果Animal中的sayName是普通函数,输出就是I love coding
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
因为箭头函数的语法其实是
this.sayName = this.sayName.bind(this)
的语法糖。如果你写过class API 的
react
,可能会知道在之前的react
中,对于函数的绑定需要在constructor
中进行this.fn = this.fn.bind(this)
的上下文绑定.于是后来babel支持了这种箭头函数的快捷写法,实际上两种写法是等同的。而正常规范里的class方法是绑定在prototype上的,也就是ES5中Animal.prototype.sayName = function(){}
这样子的写法。如图所示,箭头函数sayName是绑定在实例上的,非箭头函数是在proto上的,这便是为什么输出是父类的log,你可以理解为箭头函数实际上是等同于先new一个对象之后再对该实例对象赋值方法
从面向对象的设计角度来看,可重载的方法应是类的,非静态变量应是实例的。JavaScript 在实现时采用的是 Prototype 的方式。方法声明实际上是关联到父类的
__proto__
变量属性上,而变量则不是。箭头函数实际是匿名函数(闭包),赋值给了 sayName 变量。在调用函数时,一个对象先在直接属性里找,找不到会沿着继承链向上的
__proto__
里找。可以看到:
TS 的报错已经一目了然了
因为一个是字段一个是方法,方法在原型上,字段在 this 上,所以你的子类的方法并没有覆盖父类的字段定义。