JavaScript, We Hardly new Ya

By YUI TeamNovember 13th, 2006

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.

54 Comments

  1. Great post! It would be great to see more posts like this!!!!

  2. 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.

  3. 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 of eval() for parsing JSON (or pseudo-JSON) values. In other words, instead of eval("var myobj = " + JSONString), you can use var 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 eval in 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 calling eval(...).

    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.

  4. You said:

    Do not use new Number, new String, or new Boolean. These forms produce unnecessary object wrappers. Just use simple literals instead.

    However, I recently read the following advice:

    If your code calls methods of literal values very often, you should consider converting them into objects instead.

    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.

  5. 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.

  6. I also read the article, and thought one of the key “light bulbs” was the “Beware of implicit object conversion” topic.

    If your code calls methods of literal values very often, you should consider converting them into objects instead, as in the previous example.

    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; i

  7. 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, and Function, 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.

  8. [...] 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. [...]

  9. “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.

  10. No, it still doesn’t make sense.

    var f = sometest() ?
    function () {command1()} :
    function () {command2()};

  11. [...] JavaScript, We Hardly new Ya » Yahoo! User Interface Blog (tags: javascript optimization) [...]

  12. 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.

  13. 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.

  14. Peter Michaux said:
    November 13, 2006 at 9:54 pm

    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.

  15. [...] 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. [...]

  16. 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

  17. No, it still doesn’t make sense.

    var f = sometest() ?
    function () {command1()} :
    function () {command2()};

    And we could have an even better code in this case with something like

    var f = sometest() ?
    command1 :
    command2;

  18. JavaScript, We Hardly new Ya…

    When to use, or rather when not to use the new operator in JavaScript…

  19. Pretty good stuff to learn.

  20. 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.

  21. [...] 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. [...]

  22. [...] JavaScript, We Hardly new Ya » Yahoo! User Interface Blog [...]

  23. Tjeerd Wolterink said:
    November 15, 2006 at 9:06 am

    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.

  24. 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.

  25. Thanks for this clear and instructive article. The comments are good too.

  26. 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!

  27. 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.

  28. 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.

  29. 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() {…

  30. “Do as I say, not as I do”

  31. good article to me!!! i think {} is good to do use for
    saving bytes! and new Function() should better not use
    except peculiar instance

  32. 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. But new Function allows 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 Function can be used for example as an alternative to eval if you want to emulate Function.prototype.apply in ie5.

  33. Theodor Zoulias said:
    February 16, 2007 at 11:41 am

    ;(sometest() ? command1 : command2)(arg1, arg2, arg3)

    This coding style makes semicolons omission no longer an option.

  34. 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…….

  35. Darryl Stoflet said:
    April 19, 2007 at 10:59 am

    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?

  36. [...] JavaScript, We Hardly new Ya » Yahoo! User Interface Blog (tags: javascript optimization performance) [...]

  37. 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.)

  38. 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

  39. 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?

  40. 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.

  41. Sorry Douglas,

    Is it fair to say that:

    var a=new Object() === var a={}

    By that I mean there is absolutely no benefit/drawback/difference at all between them? there is no unnecessary object wrappers created, etc. thus making the choice purely based on syntax preference?

  42. While I agree that using the “shorthand” (JSON) version of creating arrays is desirable, it has one flaw that I have never seen discussed on any page like this…

    Using [] does not allow you to set the initial size of an array!!!

    You usually don’t have to worry about setting the initial size of an arry, so the shorthand version works well. But there are times when it is necessary to set the initial size of an array; in that case, you have to use the “new Array(x)” format (where x is the number of elements).

    (
    There is another way to set the initial array size but I think it’s even more ugly and confusing…
    var x = [];
    x[100] = 0;
    )

    For most scenarios, the shorthand version is desirable but in situations where you have to set the array size, using new Array() is really your only option.

  43. Arrays in this language do not have sizes as they do in most other languages, so there is little point in doing what you are demanding.

    I have never had occasion to write

    var x = [];
    x.length = 100;

  44. Doug: “Arrays in this language do not have sizes…”

    Wait, what? According to ECMA-262(3) § 15.4, every Array has an invariant property called “length” that is necessarily the number of non-inherited properties + 1, such that if a new property is added, “length” is increased, and if length is set to less number of non-inherited properties + 1, properties are deleted. And according to §15.4.2.2, the “new Array(len)” form initializes a new object and sets “length” to “len”.

    One would think that implementors would take advantage of this to pre-allocate a list of size (object size*len) when the “new Array(len)” form is used. I haven’t profiled the memory paging or GC, but just on speed, a micro-benchmark testing the literal constructor versus the “new Array(len)” form showed the literal form to be equally fast / minutely faster in both jsc (from WebKit, used in Safari and Google Chrome) and smjs (from SpiderMonkey, used in stable Gecko).

    Test and timings: pastie

    So, despite what one might intuitively expect, there doesn’t seem to be much difference in speed between the literal form and the sized constructor form.

    Ps. JSCore is faaaast(!) (seems too fast, did the JIT optimize away the inner loops or something!??). I’m curious how TraceMonkey will compare.

  45. MonkeeSage@gmail.com said:
    March 23, 2009 at 8:18 pm

    After thinking about this a bit, it seems I’ve incorrectly described the constraint placed on the length property of Array objects. It is *not* the case that length “is necessarily the number of non-inherited properties + 1″. The length property is only increased if the number of non-inherited properties + 1 > the current value of length, in which case length takes that value.

    Now somebody please correct me if I’m wrong, but this seems useless, *except* as a shortcut for implementors to preallocate or resize the backing data store and retreive the size of the store without itterating all the elements. But they don’t seem to be using it that way. In the benchmark above, there should be a number of reallocation / resize oprtations for the inner loop with the literal constructor form. Even if the backing store is initialized to some default size > 0, and grows exponentially every time there is an attempt to insert past the end, there should at least be a few reallocate / resize ops for 500 insertions. And that would presumably have a speed impact (even if slight) over 10,000 iterations. But the timings don’t show any speed difference over the signal:noise threshold as compared with the constructor form using the new keyword with an initial length.

    So if this dispairity between the actual number of non-inherited properties and the length property, and the constructor form with a default length, are not being utilized by implementors for optimization purposes–then what use are they? It seems like, without some kind of practical use, this is simply a chance for faux pas like this:

    var arry = new Array (20);

    // …stuff you thought initialized the array, but didn’t

    for (var i = 0; i < arry.length; ++i) {
    do_stuff (arry[i].foo); // throws
    }

    Also, slightly confusingly, mutating methods like push and pop *always* increment and decrement the length property, and operate on the index relative to the length propery (rather than the actual index of the last initialized element).

  46. I love this pattern but I have the same doubts Darryl Stoflet has.

  47. A string object and a string value are not the same thing:


    js> p = "Foo"
    Foo
    js> p.weight = 42
    42
    js> p.weight // Returns undefined
    js> q = new String("Foo")
    Foo
    js> q.weight = 42
    42
    js> q.weight
    42

    The string value cannot have new properties. The same thing is valid for other types.