为了账号安全,请及时绑定邮箱和手机立即绑定

如何检测一个函数是否称为构造函数?

如何检测一个函数是否称为构造函数?

MMTTMM 2019-10-06 16:09:59
给定一个功能:function x(arg) { return 30; }您可以用两种方法来称呼它:result = x(4);result = new x(4);第一个返回30,第二个返回一个对象。您如何检测在函数本身内部调用该函数的方式?无论您采用哪种解决方案,它都必须与以下调用一起使用:var Z = new x(); Z.lolol = x; Z.lolol();当前,所有解决方案都认为将该Z.lolol()方法称为构造函数。
查看完整描述

3 回答

?
开满天机

TA贡献1786条经验 获得超13个赞

1)您可以检查this.constructor:


function x(y)

{

    if (this.constructor == x)

        alert('called with new');

    else

         alert('called as function');

}

2)是的,在new上下文中使用时,返回值只是被丢弃


查看完整回答
1 反对 回复 2019-10-06
?
汪汪一只猫

TA贡献1898条经验 获得超8个赞

注意:现在可以在ES2015及更高版本中使用。请参阅Daniel Weiner的答案。


我认为[ES2015之前]您想要的东西是不可能的。函数内根本没有足够的信息来进行可靠的推断。


查看ECMAScript 3rd Edition规范,new x()调用时所采取的步骤实质上是:


创建一个新对象

将其内部的[[Prototype]]属性分配给的prototype属性 x

x正常调用,将新对象传递给this

如果调用x返回了对象,则返回它,否则返回新对象

对于执行代码而言,有关如何调用该函数的任何有用信息都没有,因此唯一可以在内部进行测试的x就是this值,这就是这里所有答案的作用。如您所见,作为构造函数x调用时,*的新实例与作为函数调用时所传递x的既有实例没有区别,除非您为构造时创建的每个新对象分配一个属性:xthisxx


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构造函数创建的对象”更为简洁


查看完整回答
反对 回复 2019-10-06
  • 3 回答
  • 0 关注
  • 849 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信