【问题标题】:Using getter and setter with Object.defineProperty将 getter 和 setter 与 Object.defineProperty 一起使用
【发布时间】:2017-01-23 10:11:00
【问题描述】:

我想使用 Object.defineProperty() 将数据属性转换为访问器属性。考虑导致Uncaught RangeError: Maximum call stack size exceeded错误的代码

var c = { name: 'abcde'};
Object.defineProperty(c, 'name', {
    get: function() {
        return this.name; //causes stack overflow
    },
    set: function(x) {
       this.name = x; //causes stack overflow
        }
}); 
c.name="xyz";  
console.log(c.name);

我明白为什么会出现错误。 建议的解决方案之一是从 getter 和 setter 中删除“this”,它似乎有效。

var c = { name: 'abcde'};
Object.defineProperty(c, 'name', {
    get: function() {
        return name; //removed this
    },
    set: function(x) {
       name = x; //removed this
        }
}); 
c.name="xyz";  
console.log(c.name);

发生了什么?一般来说,我想问如何使用 Object.defineProperty() 将数据属性转换为访问器属性?

【问题讨论】:

    标签: javascript ecmascript-5


    【解决方案1】:

    第二个代码实际上不起作用,因为它使用名为name全局 变量来存储值,而不是将其存储在对象c 中.

    如果不是因为 window.name 是浏览器中全局对象的默认属性,它会被 ES5“严格模式”拒绝。

    更合适的解决方法是将值存储在词法范围的私有变量中:

    var c = (function() {
        var obj = {};
        var name = "abcde";
    
        Object.defineProperty(obj, "name", {
            get: function() {
                return name;
            },
            set: function(x) {
                name = x;
            }
        });
    
        return obj;
    })();
    

    【讨论】:

    • 很棒的解决方案。但是,如何将此处的“名称”之类的数据属性转换为访问器属性?在这里,您已经关闭了名称。我最初希望它作为数据属性。
    • @BreakingBenjamin AFAIK,唯一的另一种方法是隐藏不动产,然后使用命名约定(例如前导下划线)将不动产标记为“私有”,例如您可以使用._name 来存储实际值,但可以通过.name 访问它。
    • 太奇怪了。如果您删除 getter 函数并仅定义 setter 函数,则即使您已声明属性名称,它也将是未定义的。为什么?
    猜你喜欢
    • 2021-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-09
    相关资源
    最近更新 更多