É possível implementar getters / setters dynamics em JavaScript?

Estou ciente de como criar getters e setters para propriedades cujos nomes já se conhece, fazendo algo como isto:

// A trivial example: function MyObject(val){ this.count = 0; this.value = val; } MyObject.prototype = { get value(){ return this.count  "Go away" a.value = 'bar'; alert(a.value); // --> "bar2" 

Agora, minha pergunta é, é possível definir uma espécie de get-all getters e setters como estes? Ou seja, crie getters e setters para qualquer nome de propriedade que ainda não esteja definido.

O conceito é possível em PHP usando os methods mágicos __get() e __set() (veja a documentação do PHP para obter informações sobre isso), então estou realmente perguntando se existe um JavaScript equivalente a estes?

Escusado será dizer que, idealmente, gostaria de uma solução que seja compatível com vários navegadores.

    Atualização de 2013 e 2015 (veja abaixo a resposta original de 2011) :

    Isso mudou a partir da especificação do ES2015 (também conhecido como “ES6”): o JavaScript agora tem proxies . Proxies permitem criar objects que são verdadeiros proxies para (fachadas de) outros objects. Aqui está um exemplo simples que transforma todos os valores de propriedade que são strings em todos os limites na recuperação:

     var original = { "foo": "bar" }; var proxy = new Proxy(original, { get: function(target, name, receiver) { var rv = target[name]; if (typeof rv === "string") { rv = rv.toUpperCase(); } return rv; } }); console.log("original.foo = " + original.foo); // "bar" console.log("proxy.foo = " + proxy.foo); // "BAR" 
     "use strict"; (function() { if (typeof Proxy == "undefined") { console.log("This browser doesn't support Proxy"); return; } var original = { "foo": "bar" }; var proxy = new Proxy(original, { get: function(target, name, receiver) { var rv = target[name]; if (typeof rv === "string") { rv = rv.toUpperCase(); } return rv; } }); console.log("original.foo = " + original.foo); // "bar" console.log("proxy.foo = " + proxy.foo); // "BAR" })(); 

    No Javascript moderno (FF4 +, IE9 +, Chrome 5+, Safari 5.1+, Opera 11.60+), existe Object.defineProperty . Este exemplo no MDN explica muito bem como defineProperty funciona, e torna getters e setters dynamics possíveis.

    Tecnicamente, isso não funcionará em nenhuma consulta dinâmica como a que você está procurando, mas se seus getters e setters válidos forem definidos por, digamos, uma chamada AJAX para um servidor JSON-RPC, por exemplo, você poderá usar isso em da seguinte maneira:

     arrayOfNewProperties.forEach(function(property) { Object.defineProperty(myObject, property.name, { set: property.setter, get: property.getter }); }); 

    O seguinte poderia ser uma abordagem original para este problema:

     var obj = { emptyValue: null, get: function(prop){ if(typeof this[prop] == "undefined") return this.emptyValue; else return this[prop]; }, set: function(prop,value){ this[prop] = value; } } 

    Para usá-lo, as propriedades devem ser passadas como strings. Então aqui está um exemplo de como funciona:

     //To set a property obj.set('myProperty','myValue'); //To get a property var myVar = obj.get('myProperty'); 

    Editar: Uma abordagem aprimorada, mais orientada a objects, baseada no que propus, é a seguinte:

     function MyObject() { var emptyValue = null; var obj = {}; this.get = function(prop){ return (typeof obj[prop] == "undefined") ? emptyValue : obj[prop]; }; this.set = function(prop,value){ obj[prop] = value; }; } var newObj = new MyObject(); newObj.set('myProperty','MyValue'); alert(newObj.get('myProperty')); 

    Você pode ver isso funcionando aqui .

     var x={} var propName = 'value' var get = Function("return this['" + propName + "']") var set = Function("newValue", "this['" + propName + "'] = newValue") var handler = { 'get': get, 'set': set, enumerable: true, configurable: true } Object.defineProperty(x, propName, handler) 

    isso funciona para mim