在PHP中,您可以使用"魔术" __call
功能检测方法何时被调用,即使它不存在.
public function __call($methodName, $args)
{
// do something
}
Run Code Online (Sandbox Code Playgroud)
您可以调用任何方法,并将名称和参数传递给此魔法catch-all.
在JavaScript中是否有类似的技术允许调用任何方法,即使它实际上不存在于对象上?
var foo = (function () {
return {
__call: function (name, args) { // NOT REAL CODE
alert(name); // "nonExistent"
}
}
}());
foo.nonExistent();
Run Code Online (Sandbox Code Playgroud)
ami*_*sim 23
它是使用ES6可能代理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]);
return "returns: " + args[0];
}
}
});
console.log(myProxy.foo('bar'));
Run Code Online (Sandbox Code Playgroud)
MDN上提供了浏览器兼容性.截至2017年8月,除Internet Explorer之外的所有浏览器(包括Microsoft Edge)都支持它.
有关Proxy的详细信息,请参阅此答案.
稍微建立在@amirnissim 的回答之上。
正如我们大多数人可能已经知道的那样,ES6 引入了 Proxy API,它允许我们创建一个对象(代理对象)来捕获对该对象的调用,从而我们有机会“路由”用户调用的属性任何我们可能希望的对象。
不幸的是,没有办法使用 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)
}
}
Run Code Online (Sandbox Code Playgroud)
这本质上同时为您提供了与 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?") }
Run Code Online (Sandbox Code Playgroud)
如果我们继续创建类的新实例MyProxy
,我们可以触发我们实现的自定义逻辑:
let myProxy = new MyProxy()
myProxy.test()
myProxy.hello()
myProxy.helloWorld()
Run Code Online (Sandbox Code Playgroud)
上面的例子输出:
Where art thou, hello world?
Where art thou, hello world?
Hello, world!
当然,也可以从get
函数返回任何其他类型的值,我们也可以返回字符串或整数。
为了使其更易于使用,我是否建议将该asProxy
方法包装到另一个类中,然后简单地使用包含该asProxy
方法的类扩展任何需要“魔术方法”功能的类?通过简单地asProxy
从构造函数返回该方法,您基本上可以获得与在 PHP 和 JavaScript 中看到的相同的功能。
当然,还需要某种get method
程度的可编辑性,以便仍然可以从子类处理自定义逻辑。也许通过向return this.asProxy(() => {})
然后从get
函数本身调用的 发送一个闭包?或者甚至可能将get
函数路由到对象get
上存在的方法target
?
但是请记住,这仅适用于 ES6。像 Babel 这样的转译器不能,我引用:
由于 ES5 的限制,代理不能被转译或填充。
然而,只要满足这个条件,上面提出的解决方案就可以很好地工作。例如,它是Node.js 中一个非常可行的选项。
归档时间: |
|
查看次数: |
9557 次 |
最近记录: |