ES6中class的getter和setter在继承中踩坑

在 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

你可能感兴趣的:(js算法,js类型,js设计模式,es6)