Press "Enter" to skip to content

Defensive Coding: Self-Instantiating JavaScript Constructors

A very common bug in JavaScript is to forget that the Constructor function requires a “new” operator to return the “this” object. As a result all references to the “this” object will reference the context of the caller. In a hosted environment, like a browser, this is typically the “window” object. When designing JavaScript Constructors, we can do better than to expect client code to instantiate our constructors correctly.

Similar to my previous post, I am using the example on GitHub.

If you run the run.html (from the GitHub example) in a browser, you will see that both QUnit unit tests pass by default. In reviewing the second test (as shown below), it may seem odd that this test would pass as there is no “new” operator to instantiate the object.

The following mechanism is the reason that the unit test is not failing. Even though the developer carelessly forgot to “new” up the Constructor and the developer is instead calling the function directly, the code still works.

This is attributed to the above code defensively checking to see if the “new” operator was used in calling this method. It does this by examining the “this” object. If the “this” object is an instance of the Constructor, all is good with the world. If not…i.e., the “this” object is the context of the calling method…the mechanism highlighted above will kick in.

The mechanism will “new” up a new instance of the “Example” object and will return it to the caller. When the “return new Example();” line of code is invoked, it will recursively instantiate itself.

When hearing the term “recursion”, your first impression may be that there is a possibility of an infinite loop as the code could endlessly instantiate itself. This does not happen, however, because the second time through this loop, the “this” object is indeed an instanceof the Example object and the “if” condition is falsy.

Try this yourself by commenting out or removing the code as the following shows:

Now run the run.html file and you will see that the second test now fails. See the screenshot below as an example run of run.html:

Example error after modifying the code.
Example error after modifying the code.

An alternative to hard coding the object name (e.g., the “Example” object as shown here), you could use arguments.callee instead. The reason I don’t suggest that here is that callee has been deprecated in future versions of JavaScript.

This alternative of the callee comes from the book Secrets of the JavaScript Ninja by John Resig and Bear Bibeault. I highly recommend reading the book.

An alternative technique to returning a new “Example” object could be to throw an Error instead. In other words, to inform the client that their code is defective by throwing an Error rather than covering up the issue within the Constructor by returning the new “Example” object. The decision of whether to aggressively throw or to submissively “new” the object will likely come down to the relationship that you have to your client code.

Hopefully you find this defensive coding technique helpful in your code.

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *