2017-01-23 79 views
0

我想使用Object.defineProperty()将data属性转换为accessor属性。考虑这导致Uncaught RangeError: Maximum call stack size exceeded错误使用Object.defineProperty使用getter和setter

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删除“本”,它似乎工作,这样做的代码。

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()将数据属性转换为访问器属性?

回答

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; 
})(); 
+0

真棒溶液。但是,我怎么才能将数据属性如'名称'这里转换为访问器属性?在这里你已经关闭了名字。我最初想要它作为数据属性。 –

+1

@BreakingBenjamin AFAIK,唯一的另一种方式是对一个不动产进行投影,然后使用命名约定(例如一个前导下划线)将不动产标记为“私人”,例如,你可以使用'._name'来存储实际值,但是可以通过'.name'来访问它。 – Alnitak