在PHP中,您可以检测方法何时被调用,即使它没有使用" magic" __call
功能。
public function __call($methodName, $args)
{
// do something
}
您可以调用任何方法,并将名称和参数传递给此魔法全部。
JavaScript中是否有类似的技术允许调用任何方法,即使它实际上并不存在于对象上?
var foo = (function () {
return {
__call: function (name, args) { // NOT REAL CODE
alert(name); // "nonExistent"
}
}
}());
foo.nonExistent();
答案 0 :(得分:20)
使用ES6 Proxy API:
可以var myObj = {};
var myProxy = new Proxy(myObj, {
get: function get(target, name) {
return function wrapper() {
var args = Array.prototype.slice.call(arguments);
console.log(args[0]);
}
}
});
console.log(myProxy.foo('bar')); // prints 'bar'
MDN上提供了浏览器兼容性。截至2017年8月,除Internet Explorer之外的所有浏览器(包括Microsoft Edge)都支持它。
有关代理的详细信息,请参阅this answer。
答案 1 :(得分:9)
您可以在Firefox中使用__noSuchMethod__
。不幸的是,这是非标准的...
答案 2 :(得分:3)
没有。由于JavaScript的工作方式,等价物就像Python的__getattr__
/ __getitem__
,而不是PHP的__call
,因为在检索属性时需要处理它,而不是在调用时它
然后,您可以查看像Python's __getattr__ in Javascript这样以这种方式回答问题的问题。
另见以下问题:
答案 3 :(得分:2)
建立@ amirnissim的回答。
正如我们大多数人可能已经意识到的那样,ES6 introduces the Proxy API允许我们创建一个对象(Proxy对象)来捕获对该对象的调用,从而为我们提供了一个" route&#的机会。 34;用户在对象上调用的属性,无论我们想要什么。
很遗憾没有办法使用Proxy对象扩展类,但我们可以做的是设置一个中间步骤将对象转换为代理,并将任何传入的方法调用路由到对象本身可用的方法:
class MyProxy
{
constructor ()
{
return this.asProxy()
}
/**
* Return as a proxy with this object as its target.
*/
asProxy ()
{
let handler = {
/**
* This function is called whenever any property on the Proxy
* is called.
*
* @param target the "parent" object; the object the proxy
* virtualizes
* @param prop the property called on the Proxy
*/
get: function (target, prop)
{
/* This will return the property on the "parent" object
*/
if (typeof target[prop] !== 'undefined')
return target[prop]
// TODO: implement custom logic
}
}
return new Proxy(this, handler)
}
}
这实质上为您提供了与PHP的魔术__get
方法和__call
方法相同的功能。至于__call
版本,我们只是返回一个函数供用户输入参数。
为了使用它,我们首先在TODO: implement custom logic
所在的地方添加一些自定义逻辑:
if (prop === 'helloWorld')
return function () { console.log("Hello, world!") }
else
return function () { console.log("Where art thou, hello world?") }
如果我们继续创建MyProxy
类的新实例,我们可以触发我们实现的自定义逻辑:
let myProxy = new MyProxy()
myProxy.test()
myProxy.hello()
myProxy.helloWorld()
以上示例输出:
Where art thou, hello world?
Where art thou, hello world?
Hello, world!
当然,也可以从get
函数返回任何其他类型的值,我们也可以返回一个字符串或整数。
为了使这更容易使用,我可以建议将asProxy
方法包装到另一个类中,然后简单地扩展任何需要"魔术方法的类#34;包含asProxy
方法的类的功能?只需从构造函数中返回asProxy
方法,基本上就可以获得与PHP中相同的功能。
当然,还需要get method
稍微可编辑,以便仍然可以从子类处理自定义逻辑。也许通过向return this.asProxy(() => {})
发送一个闭包,然后从get
函数本身调用?或者甚至可能将get
函数路由到get
对象上的target
方法?
但请记住,这只适用于ES6。 Transpilers such as Babel不能,and I quote:
由于ES5的限制,代理无法进行转换或填充。
只要符合这一条件,上述解决方案确实可以很好地工作。例如,它是Node.js中完全可行的选项。
答案 4 :(得分:0)
虽然这不是一种优雅的方式,因为我们已经推断出JavaScript没有__call
,method_missing
,__getattr__
,因此可以创建属性组合来创建具体功能转发到单个方法,传递用于创建它的属性。
一个例子是Myriad.js。