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
.
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.
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.
Here is the briefest summary I could make of the two strongest arguments for and against using the new
operator:
new
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.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.
new
new
operator along with
prototypal assignment is fast.See John Resig's post for a simple explanation of this technique, and for a generally deeper explanation of the inheritance model he advocates.
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:
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).
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.
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.