如何检测' new'使用了关键字?

时间:2017-05-17 16:24:49

标签: javascript

这是否特别强大(尝试检测' new'关键字是否用于创建对象)?

this.constructor.toString().indexOf('window') === -1

请记住,我并不太关心像IE6 / 7/8这样的古老浏览器。

3 个答案:

答案 0 :(得分:2)

不,它不仅不健全,而且不正确。它在构造函数中的任何位置查找字符"window",这会给出两个误报(你可以在没有new的情况下调用没有"window"的函数)和假阴性(只是因为构造函数包含"window",这并不意味着它没有使用new调用。)

在ES5及更早版本中,您完全不能完全确定 new,但您可以与以下内容保持足够接近:

if (this instanceof TheConstructorName) {
    // Yes, `new` was probably used
}

......但这可能会被打败:

var f = new TheConstructorName(); // Really called with `new`
TheConstructorName.call(f);       // Tricks it

如果您使用严格模式,this如果有人undefined,则TheConstructorName()this,但您不能仅依赖undefined TheConstructorName.call({}) ,因为有人可以执行var o = {c: TheConstructorName}; o.c();甚至this,其中任何一个都将undefined设置为if (new.target) { // Yes, `new` was used } 以外的值,即使在严格模式下也是如此。

在ES2015 +中,您可以通过查看new.target

来完全确定
class

但是,如果使用class语法,则不需要这样做;使用new 创建的构造函数不能在没有super的情况下调用(直接或间接调用var res = {};)。

答案 1 :(得分:1)

你有几个解决方案来检查这个......

ECMAScript 5

function Foo() {
  if (!(this instanceof Foo)) {
    throw new Error('Oops!');
  }

  console.log('OK');
}

new Foo(); // OK
Foo(); // Error

function Foo() {
  if (this.constructor !== Foo) {
    throw new Error('Oops!');
  }

  console.log('OK');
}

new Foo(); // OK
Foo(); // Error

ECMAScript 6

function Foo() {
  if (!new.target) {
    throw new Error('Oops!');
  }

  console.log('OK');
}

new Foo(); // OK
Foo(); // Error

答案 2 :(得分:0)

如前所述,instanceof是检测是否使用new关键字的一种非常好的方法。以下是您可以使用的一些代码,以防有人忘记new关键字,因此他们不会得到奇怪的结果:

function Foo(bar) {
    if (!(this instanceof Foo)) {
        return new Foo(bar)
    }

    this.bar = bar
    return this
}

new Foo(1, 2) // OK
Foo(3, 4) // OK