JavaScript - 未捕获的 RangeError:超出最大调用堆栈大小
2017-05-04
2877
我在使用此代码时出现错误
var book = {
year: 2004,
edition: 1
};
Object.defineProperty(book, "year", {
get: function(){
return this.year;
},
set: function(newValue){
if (newValue > 2004) {
this.year = newValue;
this.edition += newValue - 2004;
}
}
});
book.year = 2005;
alert(book.edition);
警告告诉我错误发生在 Object.set [as year]
this.year = newValue;
我很困惑为什么设置年份会导致此错误?
3个回答
设置 year 属性时,会隐式调用 set 函数。
set 函数会设置 year 属性(如果值为 > 2004)。
因此:
- 将 year 属性设置为 2005
- set 函数会将 year 属性设置为 2005
- GOTO 2 并无限循环
Quentin
2017-05-04
您正在为
year
定义一个 getter 和一个 setter。setter 在分配给
this.year = newValue;
时会再次调用 setter,这会导致无限循环。例如,您需要定义一个自定义属性
_year
,并将年份状态保留在那里:
var book = {
edition: 1
};
Object.defineProperty(book, "_year", {
value: 2004,
enumerable: false, // Hide it when looping the object
writeable: true,
configurable: true
});
Object.defineProperty(book, "year", {
get: function(){
return this.year;
},
set: function(newValue){
if (newValue > 2004) {
this._year = newValue;
this.edition += newValue - 2004;
}
},
enumerable: true, // Show this when looping
configurable: true
});
book.year = 2005;
alert(book.edition);
console.log(Object.keys(book)); // ['edition', 'year']
nils
2017-05-04
以下是导致此错误的事件序列:
-
您设置了书籍的
year
。 - 由于它是一个属性,因此该值将传递给您的 setter 函数。
-
检查已执行 - 因为在本例中它为真,所以
year
已设置。 -
哦 - 由于您刚刚设置了
year
,setter 再次运行。 - 检查继续通过,因为它一遍又一遍地接收相同的值。
- 您的浏览器开始无限循环,内存耗尽,并陷入一大堆中。
为了避免这种情况,您需要将实际值存储在对象的单独字段中(例如
this._year
),然后让您的 getter 返回该值。以下是示例:
var book = {
_year: 2004,
edition: 1
};
Object.defineProperty(book, "year", {
get: function() {
return this._year;
},
set: function(newValue) {
if (newValue > 2004) {
this._year = newValue;
this.edition += newValue - 2004;
}
}
});
book.year = 2005;
alert(book.edition);
Joe Clay
2017-05-04