直奔主题,给出如下代码:
class A {
x = 1;
}
class B extends A {
get x() {
return 2;
}
set x(v) {}
}
const a = new A();
const b = new B();
console.log(a.x);
console.log(b.x);
猜猜它们分别打印什么?
下面的代码呢:
class A {
constructor() {
this.x = 1;
}
}
class B extends A {
get x() {
return 2;
}
set x(v) {}
}
const a = new A();
const b = new B();
console.log(a.x);
console.log(b.x);
再下面的代码呢:
class A {
x = 1;
get x() {
return 2;
}
set x(v) {}
}
const a = new A();
console.log(a.x);
你猜对了吗?
对于 public field
,我们观察它在 chrome devtools 下的展现:

可以看到 x
是 A
对象的实例变量,不在其 prototype
上。
而对于 x accessor
:

x accessor
出现在了 A
对象实例的 Prototype
上。
所以可作出如下结论:
Fields are part of the instance object. Accessors are part of the object’s prototype.(fields 是对象实例的一部分,而 accessors 是对象原型的一部分。)
进而得出:
So fields are hit before methods/accessors. (fields 总是比 methods/accessors 先被访问。)
所以上面的几个问题,答案就容易推导了。
对于第一个问题,因为 x=1
作用于对象实例,而 get x
作用于对象 prototype,因此 x=1
先被访问,两个打印的都是 1
。
对于第二个问题,a.x
是 1
,而 b.x
是 2
。比较迷惑的是为什么 b.x
是 2
,因为在 contructor
方法里,this
指向的是构造完的对象,即 B
的实例,此时的 this
的 prototype 中有个 x accessor
,因此当调用 this.x=1
时,实际上是调用了 set x(v){}
这个accessor(如果不信,可以在 set x(){}
中加一句 console.log
观察)。由于该 set x
是空方法,因此 get x
会一直返回 2
。
对于第三个问题,和第一个问题一样,x=1
优先于 get x
被访问,故打印 1
。
(文章参考自一则推文讨论 https://twitter.com/davidmarkclem/status/1430914451268677635)
原文始发于微信公众号(背井):JavaScript 中的 public fields vs accessors
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/246893.html