580
votes

In another question, a user pointed out that the new keyword was dangerous to use and proposed a solution to object creation that did not use new. I didn't believe that was true, mostly because I've used Prototype, Scriptaculous and other excellent JavaScript libraries, and everyone of them used the new keyword.

In spite of that, yesterday I was watching Douglas Crockford's talk at YUI theater and he said the exactly same thing, that he didn't use the new keyword anymore in his code (Crockford on JavaScript - Act III: Function the Ultimate - 50:23 minutes).

Is it 'bad' to use the new keyword? What are the advantages and disadvantages of using it?

13
It is NOT 'bad' to use the new keyword. But if you forget it, you will be calling the object constructor as a regular function. If your constructor doesn't check its execution context then it won't notice that 'this' points to different object (ordinarily the global object) instead of the new instance. Therefore your constructor will be adding properties and methods to the global object (window). If you always check that 'this' is an instance of your object in the object function, then you won't ever have this problem.Kristian B
I don't understand this. On one hand doug discourages use of new. But when you look at the YUI library. You have to use new everywhere. Such as var myDataSource = new Y.DataSource.IO({source:"./myScript.php"}); .aditya_gaur
@aditya_gaur That's because if you need some initialization of an object, you'd have to hack up a init method if you're using the Object.create approach and call that after. Much easier to just use new which does both, sets the prototype chain and calls some initializer code.Juan Mendes
I don't think this should have been closed. Yes, it's likely to inspire some Crockford anti-fan venom but we are talking about popular advice to basically avoid a major language feature here. The mechanism that makes every JQuery object weigh almost nothing (where memory is concerned) involves using the 'new' keyword. Prefer factory methods to constantly invoking new, but don't drastically reduce your architectural options and performance potential by only using object literals. They have their place and constructors have their place. It is hands-down dated and lousy advice.Erik Reppen
TLDR: Using new isn't dangerous. Omitting new is dangerous, and therefore bad. But in ES5 you can use Strict Mode, which protects you from that danger and many others.jkdev

13 Answers

616
votes

Crockford has done a lot to popularize good JavaScript techniques. His opinionated stance on key elements of the language have sparked many useful discussions. That said, there are far too many people that take each proclamation of "bad" or "harmful" as gospel, refusing to look beyond one man's opinion. It can be a bit frustrating at times.

Use of the functionality provided by the new keyword has several advantages over building each object from scratch:

  1. Prototype inheritance. While often looked at with a mix of suspicion and derision by those accustomed to class-based OO languages, JavaScript's native inheritance technique is a simple and surprisingly effective means of code re-use. And the new keyword is the canonical (and only available cross-platform) means of using it.
  2. Performance. This is a side-effect of #1: if I want to add 10 methods to every object I create, I could just write a creation function that manually assigns each method to each new object... Or, I could assign them to the creation function's prototype and use new to stamp out new objects. Not only is this faster (no code needed for each and every method on the prototype), it avoids ballooning each object with separate properties for each method. On slower machines (or especially, slower JS interpreters) when many objects are being created this can mean a significant savings in time and memory.

And yes, new has one crucial disadvantage, ably described by other answers: if you forget to use it, your code will break without warning. Fortunately, that disadvantage is easily mitigated - simply add a bit of code to the function itself:

function foo()
{
   // if user accidentally omits the new keyword, this will 
   // silently correct the problem...
   if ( !(this instanceof foo) )
      return new foo();

   // constructor logic follows...
}

Now you can have the advantages of new without having to worry about problems caused by accidentally misuse. You could even add an assertion to the check if the thought of broken code silently working bothers you. Or, as some commented, use the check to introduce a runtime exception:

if ( !(this instanceof arguments.callee) ) 
   throw new Error("Constructor called as a function");

(Note that this snippet is able to avoid hard-coding the constructor function name, as unlike the previous example it has no need to actually instantiate the object - therefore, it can be copied into each target function without modification.)

John Resig goes into detail on this technique in his Simple "Class" Instantiation post, as well as including a means of building this behavior into your "classes" by default. Definitely worth a read... as is his upcoming book, Secrets of the JavaScript Ninja, which finds hidden gold in this and many other "harmful" features of the JavaScript language (the chapter on with is especially enlightening for those of us who initially dismissed this much-maligned feature as a gimmick).

186
votes

I have just read some parts of his Crockfords book "Javascript: The Good Parts". I get the feeling that he considers everything that ever has bitten him as harmful:

About switch fall through:

I never allow switch cases to fall through to the next case. I once found a bug in my code caused by an unintended fall through immediately after having made a vigorous speech about why fall through was sometimes useful. (page 97, ISBN 978-0-596-51774-8)

About ++ and --

The ++ (increment) and -- (decrement) operators have been known to contribute to bad code by encouraging exessive trickiness. They are second only to faulty architecture in enabling viruses and other security menaces. (page 122)

About new:

If you forget to include the new prefix when calling a constructor function, then this will not be bound to the new object. Sadly, this will be bound to the global object, so instead of augmenting your new object, you will be clobbering global variables. That is really bad. There is no compile warning, and there is no runtime warning. (page 49)

There are more, but I hope you get the picture.

My answer to your question: No, it's not harmful. but if you forget to use it when you should you could have some problems. If you are developing in a good environment you notice that.

Update

About a year after this answer was written the 5th edition of ECMAScript was released, with support for strict mode. In strict mode, this is no longer bound to the global object but to undefined.

92
votes

Javascript being dynamic language there a zillion ways to mess up where another language would stop you.

Avoiding a fundamental language feature such as new on the basis that you might mess up is a bit like removing your shiny new shoes before walking through a minefield just in case you might get your shoes muddy.

I use a convention where function names begin with a lower case letter and 'functions' that are actually class definitions begin with a upper case letter. The result is a really quite compelling visual clue that the 'syntax' is wrong:-

var o = MyClass();  // this is clearly wrong.

On top of this good naming habits help. After all functions do things and therefore there should be a verb in its name whereas classes represent objects and are nouns and adjectives with no verb.

var o = chair() // Executing chair is daft.
var o = createChair() // makes sense.

Its interesting how SO's syntax colouring has interpretted the code above.

42
votes

I am newbie to Javascript so maybe I am just not too experienced in providing a good view point to this. Yet I want to share my view on this "new" thing.

I have come from the C# world where using the keyword "new" is so natural that it is the factory design pattern that looks weird to me.

When I first code in Javascript, I don't realize that there is the "new" keyword and code like the one in YUI pattern and it doesn't take me long to run into disaster. I lose track of what a particular line is supposed to be doing when looking back the code I've written. More chaotic is that my mind can't really transit between object instances boundaries when I am "dry-running" the code.

Then, I found the "new" keyword which to me, it "separate" things. With the new keyword, it creates things. Without the new keyword, I know I won't confuse it with creating things unless the function I am invoking gives me strong clues of that.

For instance, with var bar=foo(); I have no clues as what bar could possibly be.... Is it a return value or is it a newly created object? But with var bar = new foo(); I know for sure bar is an object.

39
votes

Another case for new is what I call Pooh Coding. Winnie the Pooh follows his tummy. I say go with the language you are using, not against it.

Chances are that the maintainers of the language will optimize the language for the idioms they try to encourage. If they put a new keyword into the language they probably think it makes sense to be clear when creating a new instance.

Code written following the language's intentions will increase in efficiency with each release. And code avoiding the key constructs of the language will suffer with time.

EDIT: And this goes well beyond performance. I can't count the times I've heard (or said) "why the hell did they do that?" when finding strange looking code. It often turns out that at the time when the code was written there was some "good" reason for it. Following the Tao of the language is your best insurance for not having your code ridiculed some years from now.

25
votes

I wrote a post on how to mitigate the problem of calling a constructor without the new keyword.
It's mostly didactic, but it shows how you can create constructors that work with or without new and doesn't require you to add boilerplate code to test this in every constructor.

http://js-bits.blogspot.com/2010/08/constructors-without-using-new.html

Here's the gist of the technique:

/**
 * Wraps the passed in constructor so it works with
 * or without the new keyword
 * @param {Function} realCtor The constructor function.
 *    Note that this is going to be wrapped
 *    and should not be used directly 
 */
function ctor(realCtor){
  // This is going to be the actual constructor
  return function wrapperCtor(){
    var obj; // object that will be created
    if (this instanceof wrapperCtor) {
      // Called with new
      obj = this;
    } else {
      // Called without new. Create an empty object of the
      // correct type without running that constructor
      surrogateCtor.prototype = wrapperCtor.prototype;
      obj = new surrogateCtor();
    }
    // Call the real constructor function
    realCtor.apply(obj, arguments);
    return obj;
  }

  function surrogateCtor() {}
}

Here's how to use it:

// Create our point constructor
Point = ctor(function(x,y){
  this.x = x;
  this.y = y;
});

// This is good
var pt = new Point(20,30);
// This is OK also
var pt2 = Point(20,30);
23
votes

The rationale behind not using the new keyword, is simple:

By not using it at all, you avoid the pitfall that comes with accidentally omitting it. The construction pattern that YUI uses, is an example of how you can avoid the new keyword altogether"

var foo = function () {
    var pub= { };
    return pub;
}
var bar = foo();

Alternatively you could so this:

function foo() { }
var bar = new foo();

But by doing so you run risk of someone forgetting to use the new keyword, and the this operator being all fubar. AFAIK there is no advantage to doing this (other than you are used to it).

At The End Of The Day: It's about being defensive. Can you use the new statement? Yes. Does it make your code more dangerous? Yes.

If you have ever written C++, it's akin to setting pointers to NULL after you delete them.

20
votes

I think "new" adds clarity to the code. And clarity is worth everything. Good to know there are pitfalls, but avoiding them by avoiding clarity doesn't seem like the way for me.

16
votes

Case 1: new isn't required and should be avoided

var str = new String('asd');  // type: object
var str = String('asd');      // type: string

var num = new Number(12);     // type: object
var num = Number(12);         // type: number

Case 2: new is required, otherwise you'll get an error

new Date().getFullYear();     // correct, returns the current year, i.e. 2010
Date().getFullYear();         // invalid, returns an error
12
votes

Here is the briefest summary I could make of the two strongest arguments for and against using the new operator:

Argument against new

  1. Functions designed to be instantiated as objects using the new operator can have disastrous effects if they are incorrectly invoked as normal functions. A function's code in such a case will be executed in the scope where the function is called, instead of in the scope of a local object as intended. This can cause global variables and properties to get overwritten with disastrous consequences.
  2. Finally, writing function Func(), and then calling Func.prototype and adding stuff to it so that you can call new Func() to construct your object seems ugly to some programmers, who would rather use another style of object inheritance for architectural and stylistic reasons.

For more on this argument check out Douglas Crockford's great and concise book Javascript: The Good Parts. In fact check it out anyway.

Argument in favor of new

  1. Using the new operator along with prototypal assignment is fast.
  2. That stuff about accidentally running a constructor function's code in the global namespace can easily be prevented if you always include a bit of code in your constructor functions to check to see if they are being called correctly, and, in the cases where they aren't, handling the call appropriately as desired.

See John Resig's post for a simple explanation of this technique, and for a generally deeper explanation of the inheritance model he advocates.

9
votes

I agree with pez and some here.

It seems obvious to me that "new" is self descriptive object creation, where the YUI pattern Greg Dean describes is completely obscured.

The possibility someone could write var bar = foo; or var bar = baz(); where baz isn't an object creating method seems far more dangerous.

8
votes

I think new is evil, not because if you forget to use it by mistake it might cause problems but because it screws up the inheritance chain, making the language tougher to understand.

JavaScript is prototype-based object-oriented. Hence every object MUST be created from another object like so var newObj=Object.create(oldObj). Here oldObj is called the prototype of newObj (hence "prototype-based"). This implies that if a property is not found in newObj then it will be searched in oldObj. newObj by default will thus be an empty object but due to its prototype chain it appears to have all the values of oldObj.

On the other hand if you do var newObj=new oldObj(), the prototype of newObj is oldObj.prototype, which is unnecessarily difficult to understand.

The trick is to use

Object.create=function(proto){
  var F = function(){};
  F.prototype = proto;
  var instance = new F();
  return instance;
};

It is inside this function and only here that new should be used. After this simply use the Object.create() method. The method resolves the prototype problem.

0
votes

IMNSHO "new" is a flawed concept in 2021 JavaScript. It adds words where none are needed. It makes the return value of a function/constructor implicit and forces the use of this in the function/constructor. Adding noise to code is never a good thing.

// With new
function Point(x, y) {
    this.x = x
    this.y = y
}
let point = new Point(0,0)

Vs.

// Without new
function Point(x, y) {
    return { x, y }
}
let point = Point(0,0)