在某些javascript实现中有一个 noSuchMethod 功能(Rhino,SpiderMonkey)
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>
我在想,是否有办法为房产做类似的事情?我想编写可以在属性和方法上分派的代理类。
答案 0 :(得分:62)
目前只有一件事可以实际做到你想要的,但遗憾的是没有广泛实施:
目前只有两个工作实现,在最新的Firefox 4测试版中(自FF3.7预发布以来一直存在)和node-proxy中的服务器 - 方JavaScript - Chrome和Safari目前正在处理它。 -
它是early proposals的next version of ECMAScript之一,它是一个允许您实现虚拟化对象(代理)的API,您可以在其中分配各种< em>陷阱 -callbacks-在不同的情况下执行,你可以完全控制目前的情况-in ECMAScript 3/5只有主机对象可以做。
要构建代理对象,您必须使用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
尝试here。
代理API是如此新颖,甚至没有在Mozilla开发人员中心记录,但正如我所说,自Firefox 3.7预发布以来已经包含了一个有效的实现。
Proxy
对象在全局范围内可用,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)
我见过的唯一资源,除了提案本身就是以下教程:
编辑:更多信息即将发布,Brendan Eich最近在JSConf.eu会议上发表了演讲,您可以在此处找到他的幻灯片:
答案 1 :(得分:6)
以下是如何获得与__noSuchMethod __
类似的行为首先,这是一个简单的对象,有一个方法:
var myObject = {
existingMethod: function (param) {
console.log('existing method was called', param);
}
}
现在创建一个代理,它将捕获对属性/方法的访问权限,并将现有对象添加为第一个参数。
var myObjectProxy = new Proxy(myObject, {
get: function (func, name) {
// if property or method exists, return it
if( name in myObject ) {
return myObject[name];
}
// if it doesn't exists handle non-existing name however you choose
return function (args) {
console.log(name, args);
}
}
});
现在尝试一下:
myObjectProxy.existingMethod('was called here');
myObjectProxy.nonExistingMethod('with a parameter');
适用于Chrome / Firefox / Opera。在IE中不起作用(但已经在Edge中工作)。还在移动Chrome上进行了测试。
代理的创建可以是自动的,也是不可见的,即如果您使用工厂模式来构建对象。我这样做是为了创建可以直接从主线程调用内部函数的worker。由于这个名为Proxy的酷炫新功能,使用工作人员现在可以如此简单。有史以来最简单的工人实施:
var testWorker = createWorker('pathTo/testWorker.js');
testWorker.aFunctionInsideWorker(params, function (result) {
console.log('results from worker: ', result);
});
答案 2 :(得分:3)
我不相信这种类型的元编程在javascript中是可行的。相反,请尝试使用__noSuchMethod__
功能来实现属性getter的效果。不是跨浏览器,因为它是Mozilla extension。
var proxy = {
__noSuchMethod__: function(methodName, args) {
if(methodName.substr(0,3)=="get") {
var property = methodName.substr(3).toLowerCase();
if (property in this) {
return this[property];
}
}
}, color: "red"
};
alert(proxy.getColor());
答案 3 :(得分:0)
除了SpiderMonkey中的__defineGetter__
之外,还有__defineSetter__
,__lookupGetter__
,__lookupSetter__
和__noSuchMethod__
。
答案 4 :(得分:0)
您可以使用Proxy类。
var myObj = {
someAttr: 'foo'
};
var p = new Proxy(myObj, {
get: function (target, propName) {
// target is the first argument passed into new Proxy,
// in this case target === myObj
return 'myObj with someAttr:"' + target.someAttr
+ '" had "' + propName
+ '" called on it.';
}
});
console.log(p.nonExsistantProperty);
// outputs:
// myObj with someAttr:"foo" had "nonExsistantProperty" called on it