我想在不知道如何调用/实例化的情况下调用函数。根据我的理解,有两种方法可以使用new Foo()
或Foo()
。
因为我需要一个包装来调用这个函数,所以我们说它基本上是一个代理。我有一个函数的引用,但不知道我应该以哪种方式调用它,它应该是一个构造函数或一个普通的javascript函数。
由于似乎没有办法在两种方式之间产生分歧,我想出了以下内容。
var delegate;
var Foo = function() { };
Foo.prototype.foo = function() { alert("foo") };
var bar = function(value) { alert(value); }
function construct(constructor, args) {
function F() {
return constructor.apply(this, args);
}
F.prototype = constructor.prototype;
return new F();
}
var proxy = function() { return construct(delegate, arguments) };
delegate = bar;
proxy("bar");
delegate = Foo;
new proxy().foo();
这给了我预期的结果,似乎有效。你觉得这个解决方案有什么不好吗?用new
调用常规函数是不是很糟糕?这种技术的缺点是什么?
答案 0 :(得分:2)
是否可以区分构造函数和正常函数?
没有。每个普通(用户定义的)javascript函数都可以充当两者。在函数内部,您可能会根据this
值的外观进行一些推理,但这不可靠。
另见How to detect if a function is called as constructor?
我有一个函数的引用,但不知道我应该以哪种方式调用它,它是指构造函数还是普通的javascript函数。
但是,您不需要知道 - proxy
本身被知道它的人称为构造函数或普通函数。
你觉得我的解决方案有什么不好吗?
关于delegate
的关闭,后来改变了,在开放时是丑陋的。在你的情况下,你似乎并不需要它,普通的proxy = bar;
和proxy = Foo;
就足够了。此外,您的construct
功能看起来不必要。
用new调用常规函数是不是很糟糕?这种技术的缺点是什么?
如果函数不使用this
,则不会出现任何问题,但构造实例对象会产生开销。
对于在其他地方传递的代理函数(这样我们就不能轻易更改引用),我会使用delegate
的显式setter:
function makeProxy(delegate) {
function proxy() {
return delegate.apply(this, constructor);
}
proxy.prototype = delegate.prototype;
return {
proxy: proxy,
setTarget: function(d) {
delegate = d;
proxy.prototype = d.prototype;
}
};
}
var p = makeProxy(bar);
p.proxy("bar");
p.setTarget(Foo);
new (p.proxy)().foo();