在某些javascript实现(Rhino,SpiderMonkey)中没有 noSuchMethod 功能。
proxy = { __noSuchMethod__: function(methodName, args){ return "The " + methodName + " method isn't implemented yet. HINT: I accept cash and beer bribes" ; }, realMethod: function(){ return "implemented" ; } } js> proxy.realMethod() implemented js> proxy.newIPod() The newIPod method isn't implemented yet. HINT: I accept cash and beer bribes js>
我想知道,是否有一种方法可以对物业进行类似的处理?我想编写可以在属性和方法上分派的代理类。
更新: ECMAScript6代理现在已得到广泛支持。基本上,如果您不需要支持IE11,则可以使用它们。
代理对象使您可以定义基本操作的自定义行为,例如属性查找,赋值,枚举,函数调用等。
通过在属性访问上实现陷阱,您可以模拟非标准__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");
目前只有一件事可以实际完成您想要的事情,但是不幸的是,它并未得到广泛实施:
目前只有 两种有效的 实现方式,在最新的Firefox4beta(自FF3.7预发行版开始出现)和用于服务器端JavaScript的节点代理中,Chrome和Safari当前正在使用该实现, 。
这是一个早期的提案为[ECMAScript中的下一个版本,它是一个API,可让您实现虚拟化的对象(代理),您可分配各种陷阱-callbacks-了在不同情况下执行的,你得到完全控制目前,ECMAScript 3/5中只有主机对象可以执行此操作。
要构建代理对象,您必须使用Proxy.create方法,因为您对setand get陷阱感兴趣,所以我给您提供了一个非常简单的示例:
Proxy.create
set
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的代码:
Proxy
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参数使您能够指定一个您的代理继承自。
create
handler
proto
可用的陷阱有:
// TrapName(args) Triggered by // Fundamental traps getOwnPropertyDescriptor(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.name enumerate(): // for (name in proxy) fix(): // Object.{freeze|seal|preventExtensions}(proxy) // Derived traps has(name): // name in proxy hasOwn(name): // ({}).hasOwnProperty.call(proxy, name) get(receiver, name): // receiver.name set(receiver, name, val): // receiver.name = val keys(): // Object.keys(proxy)