ECAMScript 中的类字段(class field)在stage-2的时候使用的是[[Set]] 语义,而在stage-3改成了 [[Define]] 语义。 从Babel转译来看,就是将直接定义在原型上的方法和属性换成使用 Object.defineProperty 复制。 其实对于展开语法(Spread syntax) 处理也是这样的,有[[Set]] 语义和 [[Define]] 语义的区别。
举个例子
Define语义会导致有时候的setter、getter失效。
原始代码
class BaseFoo {
set bar(p) {
console.log('set bar', p);
}
}
class Foo extends BaseFoo {
bar = 9;
constructor(...args) {
super(...args);
}
}
Set语义
无变化
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 BaseFoo {
set bar(p) {
console.log('set bar', p);
}
}
class Foo extends BaseFoo {
constructor(...args) {
super(...args);
_defineProperty(this, "bar", 9);
}
}
问题:不会触发父类的setter了。
解决方法
将原来书写的代码改成
class BaseFoo {
set bar(p) {
console.log('set bar', p);
}
}
class Foo extends BaseFoo {
constructor(...args) {
super(...args);
this.bar = 9;
}
}
两种语义的表现都是一样的,编译后不改变,不会影响setter的继承。
|