4

In a constructor object in JS if it's created without the new keyword the 'this' variable is a reference to the window instead of the object. Is this a particularly wise idea to try and detect that?

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()
Richard
  • 4,809
  • 3
  • 27
  • 46
  • 1
    possible duplicate of [How to detect if a function is called as constructor?](http://stackoverflow.com/questions/367768/how-to-detect-if-a-function-is-called-as-constructor) – Oriol Nov 27 '13 at 19:04
  • Your code doesn't detect things like `var obj = MyObject.call(foo)` – Oriol Nov 27 '13 at 19:06
  • Sorry, why would you *want* to? Describe the preferred usage in your documentation, but it is ultimately up to the developer as to how they want to use/implement your object. That's the beauty of programming/scripting. – zamnuts Nov 27 '13 at 19:18
  • @zamnuts there are many cases where you want to be sure you were called with new. For example, if MyObject has a name, and you go this.name = 'Fred', you just wiped out window.name if this wasn't called with a new. Not want you wanted and will probably cause a bug. – user949300 Nov 27 '13 at 19:27
  • @user949300 Whose fault is that? The implementor's. IMO, it is one thing to clean up after "stupid" users (end-user/consumer), it is another thing to compensate for incompetent developers. From the POV of an advanced dev: You're telling me I can't use the module you've developed in a manner that suites me? Fine, I'll refactor your lib or roll my own, and either case send you hate mail for wasting my time. – zamnuts Nov 27 '13 at 19:36
  • I want to protect/inform the users of my library that they're doing something wrong.The .call() method makes things a little trickier though. – Richard Nov 27 '13 at 20:04

3 Answers3

8

It is fairly common to force a new object when the keyword is omitted-

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];
    }
}
kennebec
  • 102,654
  • 32
  • 106
  • 127
1

The new.target property was designed specifically for this purpose:

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

habs
  • 121
  • 4
0

I found this in SO, the last answer uses your approach;

Two ways, essentially the same under the hood. You can test what the scope of this is or you can test what this.constructor is.

but the accepted one says no reliable way to do that;

How to detect if a function is called as constructor?

EDIT.

In the book Javascript Enlightment mentions that not necesarily will be window but the parent object;

On the other hand, if you create a constructor function and call it without the use of the new keyword the this value will refer to the “parent” object that contains the function.

Community
  • 1
  • 1
Santiago Rebella
  • 2,399
  • 2
  • 22
  • 29