这是因为通过在Object的原型上定义属性,每个对象都可以获得getter/setter。而且JS中的所有东西都是一个Object,所以这意味着window
也将有一个key
setter/getter。
在您的setter/getter函数中,您只需使用key
。由于您没有明确定义key
变量,因此将使用window
上定义的变量。这是导致递归的原因。
你做obj.key = 3
,它调用的设置器,window.key = 2*value
,它调用设置器,它确实window.key = 2*value
。等等,直到达到最大调用堆栈。
不要在原型上添加一些东西,除非您在每个实例上都需要它。
而且由于您使用的是箭头函数,因此没有this
绑定到setter/getter调用,因此您无法知道与哪个实例对象进行交互。
取而代之的是不要扩展Object的原型使其成为你自己的原型,并设置/获得正确的变量/属性。
例如使用实际的构造函数,并将箭头函数更改为常规函数表达式。这将使得setter/getter可以获得对象的实例引用。然后,您需要一些方法来跟踪哪个键属于哪个实例。如果不需要隐藏这些变量,则可以简单地使用带前缀的命名属性,例如:this._key = 2*value;
否则,如果您想保持它们私密,则可以使用WeakMap。
function YourClass(){};
(function(){
var keyMap = new WeakMap();
Object.defineProperty(YourClass.prototype, 'key', {
enumerable: true,
get: function(){
return keyMap.get(this);
},
set: function(value){
if(typeof(value) == "number"){
keyMap.set(this,2*value);
}
}
});
})();
obj = new YourClass();
obj.key = 3;
console.log(obj.key);
function secondClass(){}
//make secondClass inherit from YourClass
secondClass.prototype = Object.create(
YourClass.prototype,
{
"constructor": {
configurable: true,
enumerable: false,
writable: true,
value: secondClass
}
});
var obj2 = new secondClass();
obj2.key = 16;
console.log(obj2.key);
而且因为你似乎确定使用ES6你可以只使用其中有一组类/获取语法
class YourClass {
constructor(){
this._key = null;
}
set key(value){
this._key = 2*value;
}
get key(){
return this._key;
}
}
class SecondClass extends YourClass {
constructor(){
super();
}
}
var obj = new SecondClass();
obj.key = 17;
console.log(obj.key);
哪里是'key'界定? (它很重要) – dandavis
@dandavis,它之前没有定义。我使用setter作为初始化。但即使我在原型中定义它,我也会得到同样的错误。 – TheChetan
你不能在那里定义它,你需要一个封闭的私有变量名为key(如图所示) – dandavis