在 Class 内部可以使用get和set关键字, 对某个属性设置存值函数和取值函数, 拦截该属性的存取行为。
在 Class 内部的get、set用法,看起来比较舒服,而且可以写同名函数了。
class MyClass {
constructor() {}
get prop() {
return 'getter';
}
set prop(value) {
console.log('setter: ' + value);
}
}
let inst = new MyClass();
inst.prop = 123; // setter: 123
inst.prop // setter:123
但是在继承中:
class Parents {
constructor(props) {
}
get myTest() {
return this._test;
}
}
class Child extends Parents {
constructor(props) {
super(props);// ES6 要求,子类的构造函数必须执行一次 super 函数,否则会报错。
}
set myTest(val) {
this._test = val;
}
}
let a = new Child();
a.myTest = 123;
console.log(a.myTest);
按正常的面向对象逻辑,子类里通过setter赋值了this._test,之后,自己应该可以通过getter拿回来。
但实际上并未如此,得到的结果是undefined。
换个顺序,如果子类里是getter而父类里是setter,得到的结果也一样。
而如果把getter或setter同时都放在父类,或者同时都放在子类时。我们是可以得到预期的值的。
class Base {
constructor(props) {
}
get myTest() {
return this._test;
}
set myTest(val) {
this._test = val;
}
}
class Child extends Base {
constructor(props) {
super(props);
}
}
简单地说,就是要getter与setter都在同一级的时候才会生效。
这边探索了一下原因,大概原因是这样的:
ES6的Class和其它面向对象语言并不相同。它仅仅是一个语法糖,其实上还是基于原型链的。
在第一个例子中,我们给Child加了一个setter方法后,实际上它是会产生一个伪属性的。
Child.myTest = {
set: function(val) {
this._test = val;
}
};
它是ES5的setter,但它仅有set,没有get。
这个时候去访问Child的getter时,实际上访问到了Child.myTest.get。得到的是undefined。
而第二例子里面,Child并没有创建出myTest这个伪属性。所以访问Child的getter时,它会去原型链上找,最后找到了Base上的myTest