ES6中class的getter和setter在繼承中踩坑
阿新 • • 發佈:2018-10-31
在 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