为什么子类继承父类的时候,子类重写的普通函数不会覆盖父类的箭头函数?

发布于 2022-09-12 22:59:27 字数 348 浏览 14 评论 0

如下面这段代码

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

℡寂寞咖啡 2022-09-19 22:59:27

因为箭头函数的语法其实是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(){}这样子的写法。
image
如图所示,箭头函数sayName是绑定在实例上的,非箭头函数是在proto上的,这便是为什么输出是父类的log,你可以理解为箭头函数实际上是等同于先new一个对象之后再对该实例对象赋值方法
image
image

热血少△年 2022-09-19 22:59:27

从面向对象的设计角度来看,可重载的方法应是类的,非静态变量应是实例的。JavaScript 在实现时采用的是 Prototype 的方式。方法声明实际上是关联到父类的__proto__变量属性上,而变量则不是。

箭头函数实际是匿名函数(闭包),赋值给了 sayName 变量。在调用函数时,一个对象先在直接属性里找,找不到会沿着继承链向上的__proto__里找。

console.log(monkey)

可以看到:

image

や三分注定 2022-09-19 22:59:27

image.png

Class 'Animal' defines instance member property 'sayName', but extended class 'Monkey' defines it as instance member function.

TS 的报错已经一目了然了

我偏爱纯白色 2022-09-19 22:59:27

因为一个是字段一个是方法,方法在原型上,字段在 this 上,所以你的子类的方法并没有覆盖父类的字段定义。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文