JavaScript, We Hardly new Ya
November 13, 2006 at 9:21 am by Douglas Crockford | In Development |
JavaScript is a prototypal language, but it has a new operator that tries to make it look sort of like a classical language. That tends to confuse programmers, leading to some problematic programming patterns.
You never need to use new Object() in JavaScript. Use the object literal {} instead. Similarly, don’t use new Array(), use the array literal [] instead. Arrays in JavaScript work nothing like the arrays in Java, and use of the Java-like syntax will confuse you.
Do not use new Number, new String, or new Boolean. These forms produce unnecessary object wrappers. Just use simple literals instead.
Do not use new Function to create function values. Use function expressions instead. For example,
frames[0].onfocus = new Function("document.bgColor='antiquewhite'")
is better written as
frames[0].onfocus = function () {document.bgColor = 'antiquewhite';};
The second form allows the compiler to see the function body sooner, so any errors in it will be detected sooner. Sometimes new Function is used by people who do not understand how inner functions work.
selObj.onchange = new Function("dynamicOptionListObjects["+
dol.index+"].change(this)");
If we keep function bodies in strings, the compiler can’t see them. If we keep function bodies as string expressions, we can’t see them either. It is better to not program in ignorance. By making a function that returns a function, we can explicitly pass in the values we want to bind. This allows us to initialize a set of selObj in a loop.
selObj.onchange = function (i) {
return function () {
dynamicOptionListObjects[i].change(this);
};
}(dol.index);
It is never a good idea to put new directly in front of function. For example, new function provides no advantage in constructing new objects.
myObj = new function () {
this.type = 'core';
};
It is better to use an object literal. It is smaller, faster.
myObj = {
type: 'core'
};
If we are making an object containing methods that are bound to private variables and functions, it is still better to leave off the new prefix.
var foo = new function() {
function processMessages(message) {
alert("Message: " + message.content);
}
this.init = function() {
subscribe("/mytopic", this, processMessages);
}
}
By using new to invoke the function, the object holds onto a worthless prototype object. That wastes memory with no offsetting advantage. If we do not use the new, we don’t keep the wasted prototype object in the chain. So instead we will invoke the factory function the right way, using ().
var foo = function () {
function processMessages(message) {
alert("Message: " + message.content);
}
return {
init: function () {
subscribe("/mytopic", this, processMessages);
}
};
}();
So the rule is simple: The only time we should use the new operator is to invoke a pseudoclassical Constructor function. When calling a Constructor function, the use of new is mandatory.
There is a time to new, and a time to not.
Share and extend: Bookmark with Yahoo! My Web | Bookmark with del.icio.us | digg it! | reddit!
43 Comments »
RSS feed for comments on this post. TrackBack URI
Leave a comment

Copyright © 2007 Yahoo! Inc. All rights reserved. Privacy Policy - Terms of Service
Powered by WordPress on Yahoo! Web Hosting.
Great post! It would be great to see more posts like this!!!!
Comment by Eduardo Scoz — November 13, 2006 #
Great article to get people thinking on the same page. Also, a reminder from all the hints at these techniques through other sites on JavaScript.
Comment by Joel — November 13, 2006 #
The
new Function(...)syntax is a bit bizarre, however there’s something to it that may make some sense. Specifically, because it turns a string into a function body, it can be used in place ofeval()for parsing JSON (or pseudo-JSON) values. In other words, instead ofeval("var myobj = " + JSONString), you can usevar myobj = (new Function("return " + JSONString))().This syntax isn’t obviously better in any particular way, however it does allow for JSON that is a tiny bit safer by limiting evaluation to the object that’s being returned. It also appears to execute in about half the time as
evalin Firefox (haven’t tested others yet). And if you assign the new function itself to a variable (rather than executing and disposing of it immediately), you can easily create multiple copies of the object without repeatedly callingeval(...).So, yeah,
new Function(...)is generally a silly construct and using it is usually a poor design choice, but it’s got one nice use.Comment by Mark Kawakami — November 13, 2006 #
You said:
However, I recently read the following advice:
So for a string s, they claim that s.length will be more efficient if s is a String object, vs a string literal, but I haven’t verified.
Comment by Patrick Fitzgerald — November 13, 2006 #
Most of the advice in http://dev.opera.com/articles/view/48/?page=2 is very good. But avoid new String(). Its current behavior will probably not survive in the Fourth Edition of ECMAScript.
Comment by Douglas Crockford — November 13, 2006 #
I also read the article, and thought one of the key “light bulbs” was the “Beware of implicit object conversion” topic.
I guess it’s something to be aware of if you’re writing a heavy/high performance widget or app.
Mostly, at least for the simpler loops, this can be avoided by moving the objects method call from the middle of the loop to the initialisation stage. e.g. from
for( var i = 0; i to for( var i = 0, l = s.length; iComment by Dave Transom — November 13, 2006 #
I think it’s also important to answer the question, “if I’m not supposed to do it, then why am I allowed to?” In the case of
String,Number,Boolean, andFunction, these constructors are available so that their prototypes can be augmented, not so they can be instantiated. Since these are used to create wrappers on the fly, it’s the only way to add new methods to this type of data.Comment by Nicholas C. Zakas — November 13, 2006 #
[…] Check out the rest for an interesting back-and-forth. By the way, this isn’t meant to diss the Yahoo! folks, they’re churning out some amazing libraries, patterns and hints given the constraints they need to work in and articles like this one are much appreciated. Its just that every time I dive in there, I find myself having to learn to swim every time, it really feels like its more convoluted than it needs to be. […]
Pingback by Did JavaScript need to be this confusing? « Leftshore — November 13, 2006 #
“new Function” makes sense in some cases. For example it is possible to create optimized functions with this e.g. executing command1 or command2.
var s = sometest() ? "command1();" : "command2();";
var f = new Function(s);
This is not possible with pure function expressions. In this case you can only do this using if-constructs. But they don’t have the same performance.
var f = function() {
sometest() ? command1() : command2();
}
IMO “new Function” is also the better choice compared to eval() in many cases, because it allows you to evaluate and execute code without joining it with the current scope. This should perform better.
Comment by Sebastian Werner — November 13, 2006 #
No, it still doesn’t make sense.
var f = sometest() ?
function () {command1()} :
function () {command2()};
Comment by Douglas Crockford — November 13, 2006 #
[…] JavaScript, We Hardly new Ya » Yahoo! User Interface Blog (tags: javascript optimization) […]
Pingback by BarelyBlogging » Blog Archive » links for 2006-11-14 — November 13, 2006 #
Nice post with an especially good encouragement to learn the new way of doing things. Having written enough of Javascript 1.2 type scripts I believe that embracing prototypes and JSON is a much nicer way to code (that has plenty of maintainability advantages too).
One question though (and this is something mainly regarding any of the YUI and other Yahoo! JSON stuff): why aren’t JSON objects properly quoted? There’s an RFC (http://www.ietf.org/rfc/rfc4627.txt) that defines JSON and according to it one should use double-quotes around JSON properties.
eg Foo.prototype = {
“init”: function() { … }
}
Maybe it’s that the RFC is too new or maybe its that it’s not gotten enough press. Either way I encourage the conformance to it for future-proofing and simplifiying debugging.
Comment by Josh Peters — November 13, 2006 #
By the way, Dave’s post (http://yuiblog.com/blog/2006/11/13/javascript-we-hardly-new-ya/#comment-15132) seemed to have an extra code element in it making the rest of the page look bad.
Comment by Josh Peters — November 13, 2006 #
new…
…
Trackback by simon's ramblings — November 13, 2006 #
From Flanagan’s 5th edition
“A last, very important point about the Function() constructor is that the functions it creates do not use lexical scoping; instead, they are always compiled as if they were top-level functions…”
I can imagine this might come in handy some time to create a function with a clean scope chain. Could circular event handler memory leaks in IE be avoided by using the constructor function instead of a function literal? Maybe not the most efficient way to do this but it is nice to have options in case some new browser bug comes along that can only be solved by using the function constructor function. One day that might be true for some other constructors like String and Array.
Comment by Peter Michaux — November 13, 2006 #
[…] One of the article is by Douglas Crockford that talks about when to use the new operator and avoiding the use of Number, String intrinsic objects when not necessary. The other article is by Mark Wilton on writing efficient JavaScript. […]
Pingback by gopalarathnam.com - Some very nice JavaScript posts — November 13, 2006 #
Douglas Crockford said:
[quote]
No, it still doesn’t make sense.
var f = sometest() ?
function () {command1()} :
function () {command2()};
[/quote]
how about:
var f = someTest()? command1 : command2;
f();
I always wondered why the JS gurus only use new for constructors, I’ve been following that principle for some time - now I know why!
–
Fred
Comment by OzFred — November 13, 2006 #
And we could have an even better code in this case with something like
var f = sometest() ?command1 :
command2;
Comment by Masklinn — November 13, 2006 #
JavaScript, We Hardly new Ya…
When to use, or rather when not to use the new operator in JavaScript…
Trackback by Arve Bersvendsen — November 14, 2006 #
Pretty good stuff to learn.
Comment by milo317 — November 14, 2006 #
I’ve hardly programmed in JavaScript, even though I like to program and do so almost every day. Your post is quite helpful for someone like me, who gets the point of your ideas.
Thanks and nice job.
Comment by Joao — November 14, 2006 #
[…] Douglas Crockford, JavaScript genius, presents an article on the use of "new" when creating objects in JavaScript. Excellent read that will make your code better. I know I’ll use his <select> code somewhere. […]
Pingback by A Modern Fable (AJM) » Blog Archive » Using "new" JavaScript — November 14, 2006 #
[…] JavaScript, We Hardly new Ya » Yahoo! User Interface Blog […]
Pingback by del.icio.us bookmarks - 2006-11-14 — November 14, 2006 #
I do not agree. Using new emphazises the use of a new instance of an object.
I think:
var a=new Object();
Is much better than:
var a={};
You right that javascript is not a truely object-oriented language. But this does not mean using the new keyword is something stupid. Sometimes it is even better.
I think it also depends on your coding style.
Comment by Tjeerd Wolterink — November 15, 2006 #
new Object() is in no way better than {}, except that it might be more comfortable for programmers who want to be unaware of the language they are working in.
I did not say that JavaScript was not object-oriented. It is object oriented. But it is not classical.
I did not use the word stupid to describe the use of new. My advice on new is to always use it when it is required, and to never use it when it isn’t.
Comment by Douglas Crockford — November 15, 2006 #
Thanks for this clear and instructive article. The comments are good too.
Comment by bill — November 15, 2006 #
BTW, all comments after http://yuiblog.com/blog/2006/11/13/javascript-we-hardly-new-ya/#comment-15132 are unreadable in IE.
Comment by A — November 16, 2006 #
Why, why, WHY people write comments others can’t see or read? How you create comments that are too long to fit in the area allowed?!? And why you do it even if you know some ‘fine trick’ to do so? Just to show others you CAN do it?!? Doesn’t make sense - at least not to me.
I have been typing here loooong sentences but it has wrapped nicely - at least when typed - but I’m interested to see what it will look like when published. Or IF published… :-)
The original article was just GREAT! Good job.
Thanks and keep up the good work!
Comment by Some Finnish — November 16, 2006 #
WRT to using new Function(string), I’ve found only one decent usage for it, and it had nothing to do with client-side coding…I used it in a classic ASP system where I was loading functionality from text files in order to execute in a specific context. Another words, like a controlled eval.
The point (for me anyways) is the there is enough of a use case for it that I feel it should definitely remain in the lang, although I definitely agree with Doug–it’s too easy to abuse by those who don’t know the consequences of usage.
Also, I’m not sure I agree with the factory approach you demonstrate as a replacement for defining and creating an object on the fly (i.e. new (function(){ … })(); yes, you avoid the overhead of a prototype but the nature of the construct means it’s unlikely this will be abused via lots of calls (unless someone does something ridiculous like do this in a loop or something). There is another *slight* benefit to using new in that situation: you can then mix objects into it’s prototype, if you were feeling adventurous. Though at that point its also a little ridiculous.
So many little points, so little time.
Comment by Tom Trenka — November 17, 2006 #
OK, maybe my example was a little bad. Normally, in the simple case I mentioned this maybe make no sense. But what, if the code is much more complex e.g. you generate functions for different scenarios automatically. Then it’s better to “compile” the result with “new Function” instead of doing these things inside the execution. For example qooxdoo contains a so named property implementation, where the API itself generates setter and getter pairs depending on the configuration of the property. It’s much better to use “new Function” here instead of compute the the stuff each time a setter is executed. The new system we currently plan have a much better performance than the version without “new Function” previously used.
Comment by Sebastian Werner — November 17, 2006 #
Is there a reason then that this construct is used several times in many different places in the YUI! Library?
YAHOO.util.AnimMgr = new function() {…
YAHOO.util.Bezier = new function() {…
YAHOO.widget.DateMath = new function() {…
Comment by Scott — November 24, 2006 #
“Do as I say, not as I do”
Comment by Frankie Robertson — November 27, 2006 #
good article to me!!! i think {} is good to do use for
saving bytes! and new Function() should better not use
except peculiar instance
Comment by fly — December 4, 2006 #
Well, you definitely have a point with array and object initialisers or literals for primitive types, but there is a quite strong argument in favour of
new Function, I think. The reason is: function declarations and function initialisers are locally scoped, in other words create closures. Butnew Functionallows the creation of a globally scoped function object in a nested scope, so no closure of the current scope is created. Practical if you want to get around some common memory leaks.Also,
new Functioncan be used for example as an alternative toevalif you want to emulateFunction.prototype.applyin ie5.Comment by liorean — January 13, 2007 #
;(sometest() ? command1 : command2)(arg1, arg2, arg3)
This coding style makes semicolons omission no longer an option.
Comment by Theodor Zoulias — February 16, 2007 #
Javascript Best Practices…
A tentative repository of JavaScript bestpractices with examples (WORK IN PROGRESS). @TODO: Cleanup and reorder 1. Avoid global functions or variables It is easy to forget how/where these are/were instantiated…….
Trackback by Confluence: Ask Site Engineering — March 20, 2007 #
Good stuff! I also just watched the Advanced JavaScript videos on
YUI Theater and feel this is a lot of great info
to absorb.
Couple of questions tho…
Firstly, without new (as you state) you are giving up the prototype object. But I thought one very real benefit of the prototype object is to assign methods to them once and have them shared by all, thus saving space. It seems your recommended obj literal notation requires the repeated inclusion of inline functions for every object created. I presume you consider this an acceptable trade off?
Secondly, how do you represent static variable/methods (public or private) without the use of new?
Comment by Darryl Stoflet — April 19, 2007 #
[…] JavaScript, We Hardly new Ya » Yahoo! User Interface Blog (tags: javascript optimization performance) […]
Pingback by Shall We Zen » links for 2007-05-16 — May 16, 2007 #
For all I know there’s no need to use ‘new’ for new functions. Just ‘Function’ will do. I use it to convert a function string (for example from a JSON-like string) to a real function. Like this:
var freshFunction = function(args,body) {
if (args.length>0) {
var sArgs = args.join(’,');
} else {
var sArgs = ”;
}
return Function(sArgs,body);
}
var fnFromString = function(fnStr) {
var f1 = f2 = fnStr.replace(/\n|\r/g,”),
f1a = (f1.split(/\{/i))[0],
f1b = (f1a.split(/\(/i))[1].replace(/\)/,”).trim();
if (f1b.length>0){
var fx = f1b.split(’,');
} else {
var fx = [];
}
// get function body
f2 = f2.replace(/(^function.+\{)(.+)(\}$)/i,”$2″);
return freshFunction(fx,f2);
}
(sorry, perhaps this is posted twice: I am not sure the post came trough, firefox told me the connection was reset after clicking the submit button.)
Comment by Renzo Kooi — June 3, 2007 #
A bit off topic perhaps, but may be interesting. I slightly modified Douglas Crockfords ‘object’ function to this:
function object(o) {
function F(){}
F.prototype = o;
return F.prototype;
}
Now I am able to do this:
function someConstructor() {
[code]
return object(this);
}
And point to someConstructor without using ‘new’ or ‘object’, like this:
var myObject = someConstructor();
See an (fairly useless) example @ My website
Comment by Renzo — June 3, 2007 #
In addition to my last comment, I carried it one step further and augmented Object like this:
Object.prototype.toObject = function() {
var object = function(o) {
function F(){}
F.prototype = o;
return F.prototype;
}
return object(this);
}
So now I am able to rewrite someConstructor like this:
function someConstructor() {
[code]
return this.toObject();
}
Worked in my code, but not sure if this could have unforeseen consequences. Anyone has an idea about that?
Comment by Renzo Kooi — June 5, 2007 #
Dear Scott,
new function(...) { ... }
is (mostly) equivalent to
(function(...) { ... }) ()
(The function is defined and evaluated in-place, oftentimes to create private, closed-over data, and oftentimes to do a switch against the current browser or some other environment feature to determine what function you actually want to use later on, instead of constantly testing the environment every time you call that function.)
Evaluation in-place using parentheses is more efficient, but syntactically ugly, and it’s not clear until the very end that it’s being evaluated in-place. Using the new keyword is less efficient and less immediately obvious unless you’re familiar with the style, but its syntax is nicer and, assuming you’ve seen the style before, it’s clear up-front that the function is being defined and evaluated in-place.
Comment by Jay — July 10, 2007 #
[…] JavaScript, We Hardly new Ya […]
Pingback by GANCHIKU.com » JavaScript Module Patternいいね。半年遅れだけど。。。 — November 17, 2007 #