给定一个功能:
function x(arg) { return 30; }
您可以用两种方式来称呼它:
result = x(4); result = new x(4);
第一个返回30,第二个返回一个对象。
您如何检测 在函数本身内部 调用 该函数的方式 ?
无论您采用哪种解决方案,它都必须与以下调用一起使用:
var Z = new x(); Z.lolol = x; Z.lolol();
当前所有解决方案都认为将该Z.lolol()方法称为构造函数。
Z.lolol()
我认为[ES2015之前]您想要的东西是不可能的。函数内根本没有足够的信息来进行可靠的推断。
查看ECMAScript 3rd Edition规范,new x()调用时所采取的步骤实质上是:
new x()
x
this
对于执行该代码而言,没有什么有用的关于函数调用的方法,因此,唯一可以在内部进行测试的x就是this值,这就是所有答案的作用。正如您所观察到的,的新实例x时调用x的构造函数是从预先存在的实例不可区分的x方式是:传递this时调用x一个函数, 除非* 你指定一个属性被创建的每个新的对象x,因为它构造:
function x(y) { var isConstructor = false; if (this instanceof x // <- You could use arguments.callee instead of x here, // except in in EcmaScript 5 strict mode. && !this.__previouslyConstructedByX) { isConstructor = true; this.__previouslyConstructedByX = true; } alert(isConstructor); }
显然,这并不理想,因为您现在x可以覆盖每个由此构造的对象的多余的属性,但是我认为这是您可以做的最好的事情。
(*) “ instance of”是一个不准确的术语,但足够接近,并且比“ x作为构造函数调用而创建的对象”更为简洁