【问题标题】:Detecting if the new keyword was used inside the constructor?检测是否在构造函数中使用了 new 关键字?
【发布时间】:2013-11-27 19:00:26
【问题描述】:

在 JS 的构造函数对象中,如果它是在没有 new 关键字的情况下创建的,那么“this”变量是对窗口而不是对象的引用。尝试检测它是不是一个特别明智的想法?

function MyObject ()
{
    if (this === window) {
        alert('[ERROR] Oopsy! You seem to have forgotten to use the "new" keyword.');
        return;
    }

    // Continue with the constructor...
}

// Call the constructor without the new keyword
obj = MyObject()

【问题讨论】:

  • 你的代码没有检测到像var obj = MyObject.call(foo)这样的东西
  • 抱歉,您为什么要想要?在您的文档中描述首选用法,但最终取决于开发人员如何使用/实现您的对象。这就是编程/脚本的美妙之处。
  • @zamnuts 在很多情况下,您希望确保您被调用 new。例如,如果 MyObject 有一个名称,并且您使用 this.name = 'Fred',如果 this 没有用 new 调用,那么您只是清除了 window.name。不想要你想要的并且可能会导致错误。
  • @user949300 这是谁的错?实施者的。 IMO,在“愚蠢”用户(最终用户/消费者)之后清理是一回事,补偿无能的开发人员是另一回事。来自高级开发人员的 POV:您是在告诉我,我不能以适合我的方式使用您开发的模块?好吧,我会重构你的库或者我自己的库,无论哪种情况都会向你发送讨厌的邮件,因为它浪费了我的时间。

标签: javascript object


【解决方案1】:

当关键字被省略时,强制一个 new 对象是相当普遍的-

function Group(O){
    if(!(this instanceof Group)) return new Group(O);
    if(!O || typeof O!= 'object') O= {};
    for(var p in O){
        if(O.hasOwnProperty(p)) this[p]= O[p];
    }
}

【讨论】:

    【解决方案2】:

    我在 SO 中找到了这个,最后一个答案使用了你的方法;

    两种方式,本质上是相同的。你可以测试一下 this is 的范围,或者你可以测试 this.constructor 是什么。

    但被接受的人说没有可靠的方法来做到这一点;

    How to detect if a function is called as constructor?

    编辑。

    在 Javascript Enlightment 书中提到,不一定是窗口,而是父对象;

    另一方面,如果你创建一个构造函数并调用它 如果不使用 new 关键字,this 值将引用 包含函数的“父”对象。

    【讨论】:

      【解决方案3】:

      new.target 属性专为此目的而设计:

      function Foo() {
        if (!new.target) { throw 'Foo() must be called with new'; }
      }
      

      https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new.target

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-08-21
        • 1970-01-01
        • 1970-01-01
        • 2014-05-03
        • 1970-01-01
        • 2013-02-15
        相关资源
        最近更新 更多