2017-01-23 2 views
0

Я хочу преобразовать свойство data в свойство accessor с помощью Object.defineProperty(). Рассмотрим для этого код, который приводит к Uncaught RangeError: Maximum call stack size exceeded ошибкиИспользование getter и setter с Object.defineProperty

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); 

я понял, почему урожай ошибок в. Один из предлагаемого решения заключается в удалении «это» из геттер и сеттер, и это похоже на работу.

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); 

Что происходит? В общем, я хочу спросить, как преобразовать свойство data в свойство accessor с помощью Object.defineProperty()?

ответ

1

Второй код фактически не работает, поскольку он использует переменную глобальной под названием name, чтобы сохранить значение, вместо того, чтобы хранить его в объекте c.

Это будет отклонено ES5 «строгим режимом», если бы не тот факт, что window.name является свойством по умолчанию глобального объекта в браузерах.

Более подходящее исправление будет хранить значение в лексический контекстном частной переменном:

var c = (function() { 
    var obj = {}; 
    var name = "abcde"; 

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

    return obj; 
})(); 
+0

Удивительное решения. Но как же тогда я могу преобразовать свойство данных, например «имя» здесь, в свойство accessor? здесь вы сохранили имя в закрытии. Сначала я хочу, чтобы это свойство данных. –

+1

@BreakingBenjamin AFAIK, единственный способ - затенять реальное свойство, а затем просто использовать соглашения об именах (например, ведущее подчеркивание), чтобы пометить реальное свойство как «личное», так, например, вы можете использовать '._name' для хранения фактического значения, но получить доступ к нему через' .name'. – Alnitak

Смежные вопросы