暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

JavaScript 中的 public fields vs accessors

背井 2021-08-28
692

直奔主题,给出如下代码:

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)


文章转载自背井,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论