简体   繁体   English

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

[英]How to detect whether the 'new' keyword was used?

Is this particularly robust (to try and detect whether the 'new' keyword was used to create an object)? 这是否特别健壮(尝试并检测是否使用“ new”关键字创建对象)?

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

Bear in mind I don't care too much about ancient browsers like IE6/7/8. 请记住,我不太在意IE6 / 7/8等古老的浏览器。

No, it's not only not robust, it's incorrect. 不,它不仅不够健壮,而且是不正确的。 It looks for the characters "window" anywhere in the constructor function, which gives both false positives (you can call a function without new without "window" appearing in it anywhere) and false negatives (just because the constructor contains "window" , that doesn't mean it wasn't called with new ). 它会在构造函数中的任何位置查找字符"window" ,这会同时带来误报(您可以调用不带new的函数而在任何地方都不会出现"window"的情况)和否定负(仅因为构造函数包含"window" ),并不表示未使用new调用它。

In ES5 and earlier, you can't be absolutely sure new was used at all, but you can be close enough with: 在ES5和更早的版本中,您不能完全确定是否使用过new ,但是您可以通过以下方式足够接近:

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

...but that can be defeated: ...但是可以战胜:

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

If you use strict mode, this will be undefined if someone just does TheConstructorName() , but you can't just rely on this being undefined , because someone could do TheConstructorName.call({}) or even var o = {c: TheConstructorName}; oc(); 如果您使用严格模式, thisundefined ,如果有人只是做TheConstructorName()但你不能仅仅依靠thisundefined ,因为有人可以做TheConstructorName.call({})甚至var o = {c: TheConstructorName}; oc(); var o = {c: TheConstructorName}; oc(); , either of which set this to a value other than undefined , even in strict mode. 其中的任一个设置this对以外的值undefined即使在严格的模式,。

In ES2015+, you can be completely sure by looking at new.target : 在ES2015 +中,通过查看new.target可以完全确定:

if (new.target) {
    // Yes, `new` was used
}

You don't need to do that if you use class syntax, though; 但是,如果您使用class语法,则不需要这样做。 constructors created with class can't be called without new (directly or indirectly as super ). 与创建的构造class 不能被称为无new (直接或间接作为super )。

You have a couple of solutions to check this... 您有几种解决方案可以检查此问题...

ECMAScript 5 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 ECMAScript 6

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

As was previously mentioned, instanceof is a pretty good way to detect whether the new keyword was used. 如前所述, instanceof是检测是否使用了new关键字的一种很好的方法。 Here is some code you can use in case someone forgets the new keyword, so they don't get weird results: 如果有人忘记了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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM