更新: ECMAscript6代理现在已得到广泛支持。基本上,如果您不需要支持IE11,则可以使用它们。
代理对象使您可以定义基本操作的自定义行为,例如属性查找,赋值,枚举,函数调用等。
用ES6代理模拟__noSuchMethod__
通过在属性访问上实现陷阱,您可以模拟非标准
__noSuchMethod__陷阱的行为:
function enableNoSuchMethod(obj) { return new Proxy(obj, { get(target, p) { if (p in target) { return target[p]; } else if (typeof target.__noSuchMethod__ == "function") { return function(...args) { return target.__noSuchMethod__.call(target, p, args); }; } } });}// Example usage:function Dummy() { this.ownProp1 = "value1"; return enableNoSuchMethod(this);}Dummy.prototype.test = function() { console.log("Test called");};Dummy.prototype.__noSuchMethod__ = function(name, args) { console.log(`No such method ${name} called with ${args}`); return;};var instance = new Dummy();console.log(instance.ownProp1);instance.test();instance.someName(1, 2);instance.xyz(3, 4);instance.doesNotExist("a", "b");原始答案
目前只有一件事可以实际完成您想要的事情,但是不幸的是,它并未得到广泛实施:
- ECMAscript和声代理。
目前只有 两种有效的 实现方式,在最新的Firefox4beta(自FF3.7预发行版开始出现)和用于服务器端Javascript的节点代理中,Chrome和Safari当前正在使用该实现,
。
这是一个早期的提案为[ECMAscript中的下一个版本,它是一个API,可让您实现虚拟化的对象(代理),您可分配各种陷阱-callbacks-了在不同情况下执行的,你得到完全控制目前,ECMAscript
3/5中只有主机对象可以执行此操作。
要构建代理对象,您必须使用
Proxy.create方法,因为您对
setand
get陷阱感兴趣,所以我给您提供了一个非常简单的示例:
var p = Proxy.create({ get: function(proxy, name) { // intercepts property access return 'Hello, '+ name; }, set: function(proxy, name, value) { // intercepts property assignments alert(name +'='+ value); return true; }});alert(p.world); // alerts 'Hello, world'p.foo = 'bar'; // alerts foo=bar在这里尝试。
编辑: 代理API不断发展,
Proxy.create为了使用
Proxy构造函数而删除了该方法,请参见以上更新为ES6的代码:
const obj = {};const p = new Proxy(obj, { get(target, prop) { // intercepts property access return 'Hello, '+ prop; }, set(target, prop, value, receiver) { // intercepts property assignments console.log(prop +'='+ value); Reflect.set(target, prop, value, receiver) return true; }});console.log(p.world);p.foo = 'bar';Proxy API太新了,甚至没有在Mozilla开发人员中心上进行记录,但是正如我所说,自Firefox 3.7预发行版以来,已经包含了有效的实现。
该
Proxy对象在全局范围内可用,并且该
create方法可以带有两个参数,一个
handler对象是一个简单的对象,该对象包含名为要实现的陷阱的属性,一个可选
proto参数使您能够指定一个您的代理继承自。
可用的陷阱有:
// TrapName(args) Triggered by// Fundamental trapsgetOwnPropertyDescriptor(name):// Object.getOwnPropertyDescriptor(proxy, name)getPropertyDescriptor(name): // Object.getPropertyDescriptor(proxy, name) [currently inexistent in ES5]defineProperty(name, propertyDescriptor): // Object.defineProperty(proxy,name,pd)getOwnPropertyNames(): // Object.getOwnPropertyNames(proxy) getPropertyNames(): // Object.getPropertyNames(proxy) delete(name): // delete proxy.nameenumerate(): // for (name in proxy)fix(): // Object.{freeze|seal|preventExtensions}(proxy)// Derived trapshas(name): // name in proxyhasOwn(name): // ({}).hasOwnProperty.call(proxy, name)get(receiver, name):// receiver.nameset(receiver, name, val): // receiver.name = valkeys(): // Object.keys(proxy)


