ECAMScript 中的Set语义和Define语义

ECAMScript 中的类字段(class field)在stage-2的时候使用的是[[Set]] 语义,而在stage-3改成了 [[Define]] 语义。
从Babel转译来看,就是将直接定义在原型上的方法和属性换成使用 Object.defineProperty复制。
其实对于展开语法(Spread syntax) 处理也是这样的,有[[Set]] 语义和 [[Define]] 语义的区别。

举个例子

Define语义会导致有时候的setter、getter失效。

原始代码

class BaseFoo {
  _bar;
  set bar(p) {
    this._bar = p;
    console.log('set bar', p);
  }
  get bar(){
    return this._bar;
  }
}
class Foo extends BaseFoo {
  bar = 9;
  constructor(...args) {
    super(...args);
  }
}

Set语义

class BaseFoo {
  _bar;
  set bar(p) {
    this._bar = p;
    console.log('set bar', p);
  }
  get bar(){
    return this._bar;
  }
}
class Foo extends BaseFoo {
  constructor(...args) {
    super(...args);
    this.bar = 9;
  }
}

Define语义

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

}

class Foo extends BaseFoo {
  constructor(...args) {
    super(...args);

    _defineProperty(this, "bar", 9);
  }
}

问题:不会触发父类的setter了,以后修改子类的对象的bar参数也不会触发父类的setter。

解决方法

将原来书写的代码改成,就是明确使用set

class Foo extends BaseFoo {
  constructor(...args) {
    super(...args);
    this.bar = 9;
  }
}

两种语义的表现都是一样的,编译后不改变,不会影响setter的继承。

我们在书写代码的时候,需要明白自己的属性是要用set和define,需要不需要继承父类的setter。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>