有没有可能在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)
这对我有用