有没有可能在JavaScript中实现dynamicgetter / setter?

我知道如何通过执行如下操作来为名称已知的属性创buildgetter和setter:

// A trivial example: function MyObject(val){ this.count = 0; this.value = val; } MyObject.prototype = { get value(){ return this.count < 2 ? "Go away" : this._value; }, set value(val){ this._value = val + (++this.count); } }; var a = new MyObject('foo'); alert(a.value); // --> "Go away" a.value = 'bar'; alert(a.value); // --> "bar2" 

现在,我的问题是,是否有可能定义类似这样的全面的getter和setter? 也就是说,为任何尚未定义的属性名称创buildgetter和setter。

这个概念在PHP中可以使用__get()__set()魔术方法(请参阅PHP文档获取关于这些方面的信息),所以我真的在问有没有与这些方法相当的JavaScript?

不用说,我理想上喜欢跨浏览器兼容的解决scheme。

2013年和2015年更新 (见下文为2011年的原始答案)

这改变了ES2015(又名“ES6”)规范:JavaScript现在有代理 。 代理可以让你创build对象作为其他对象(正面)的真实代理。 下面是一个简单的例子,它将string的任何属性值都转换为检索时的所有上限:

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

在现代的Javascript(FF4 +,IE9 +,Chrome 5 +,Safari 5.1 +,Opera 11.60 +)中,有Object.defineProperty 。 MDN上的这个例子很好地解释了defineProperty是如何工作的,并且使得dynamicgetter和setter成为可能。

从技术上讲,这不适用于你正在寻找的任何dynamic查询,但是如果你的有效getter和setter是通过AJAX调用JSON-RPC服务器来定义的,那么你可以使用它采取以下方法:

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

以下可能是对这个问题的原始方法:

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

为了使用它,属性应该作为string传递。 所以这里是一个如何工作的例子:

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

编辑:基于我提出的改进,更面向对象的方法如下:

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

你可以看到它在这里工作。

 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) 

这对我有用