例如这段代码:
function stuff() {
this.onlyMethod = function () {
return something;
}
}
// some error is thrown
stuff().nonExistant();
有没有办法像PHP的__call
那样做对象内部的后备?
function stuff() {
this.onlyMethod = function () {
return something;
}
// "catcher" function
this.__call__ = function (name, params) {
alert(name + " can't be called.");
}
}
// would then raise the alert "nonExistant can't be called".
stuff().nonExistant();
也许我会解释一下我正在做的事情。
该对象包含另一个对象,该对象具有应该可以通过此对象直接访问的方法。但是这些方法对于每个对象都是不同的,所以我不能只是路由它们,我需要能够动态地调用它们。
我知道我可以将其中的对象作为主对象stuff.obj.existant()
的属性,但我只是想知道我是否可以避免它,因为主要对象是一种包装器,只是添加一些功能暂时(并使同时更容易访问对象)。
答案 0 :(得分:13)
嗯,似乎和谐(ES6),会有一种方式,与其他programing languages的方式相比,它更复杂。基本上,它涉及使用Proxy内置对象在对象上创建包装器,并修改其在其上实现的默认行为:
obj = new Proxy({},
{ get : function(target, prop)
{
if(target[prop] === undefined)
return function() {
console.log('an otherwise undefined function!!');
};
else
return target[prop];
}
});
obj.f() ///'an otherwise undefined function!!'
obj.l = function() {console.log(45);};
obj.l(); ///45
代理会将处理程序未处理的所有方法转发到普通对象中。所以它就好像它不在那里,从代理你可以修改目标。还有更多的处理程序,甚至一些修改原型获取,以及任何属性访问的设置者是!。
正如您所想,目前并非所有浏览器都支持此功能,但在Firefox中您可以非常轻松地使用代理界面,只需转到MDN docs
如果设法在这上面添加一些语法糖,这会让我更开心,但无论如何,以一种已经很强大的语言拥有这种力量是很好的。祝你今天愉快! :)
PD:我没有复制rosettacode js条目,我更新了它。
答案 1 :(得分:10)
有一种方法可以为不存在的方法调用通用处理程序,但它是非标准的。查看Firefox的noSuchMethod。将允许您动态地将调用路由到未定义的方法。似乎v8也是getting support。
要使用它,请在任何对象上定义此方法:
var a = {};
a.__noSuchMethod__ = function(name, args) {
console.log("method %s does not exist", name);
};
a.doSomething(); // logs "method doSomething does not exist"
但是,如果你想要一个跨浏览器的方法,那么如果要走的话,那么简单的try-catch阻塞:
try {
a.doSomething();
}
catch(e) {
// do something
}
如果你不想在整个代码中编写try-catch,那么你可以在主对象中添加一个包装器,通过它来路由所有函数调用。
function main() {
this.call = function(name, args) {
if(this[name] && typeof this[name] == 'function') {
this[name].call(args);
}
else {
// handle non-existant method
}
},
this.a = function() {
alert("a");
}
}
var object = new main();
object.call('a') // alerts "a"
object.call('garbage') // goes into error-handling code
答案 2 :(得分:1)
您还可以检查方法是否存在。
if(a['your_method_that_doesnt_exist']===undefined){
//method doesn't exist
}
答案 3 :(得分:1)
似乎你了解JS的方式。 不幸的是,我不知道语言中有这样的功能,我很确定它不存在。在我看来,你最好的选择是使用统一的界面并扩展它,或者扩展你的对象继承的原型(然后你可以在继续使用方法调用之前使用instanceof)或使用有点麻烦的'&&和“运算符,以避免访问不存在的属性/方法:
obj.methodName && obj.methodName(art1,arg2,...);
您还可以使用Anurag的建议('call')扩展Object原型。