JavaScript - 未捕获RangeError:超出最大调用堆栈大小

时间:2017-05-04 10:25:40

标签: javascript

使用此代码时出错了

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 个答案:

答案 0 :(得分:1)

设置年份属性时,隐式调用set函数。

set函数设置year属性(如果值为> 2004)。

所以:

  1. 您将年份属性设置为2005
  2. set函数将year属性设置为2005
  3. GOTO 2和无限循环

答案 1 :(得分:0)

以下是导致此错误的事件序列:

  • 您设置了图书的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);

答案 2 :(得分:0)

您正在为year定义一个getter和一个setter。分配给this.year = newValue;时,setter会再次调用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']