new YaJavaScript 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.
November 13, 2006 at 10:24 am
Great post! It would be great to see more posts like this!!!!
November 13, 2006 at 10:28 am
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.
November 13, 2006 at 10:40 am
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.November 13, 2006 at 10:47 am
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.
November 13, 2006 at 11:12 am
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.
November 13, 2006 at 1:45 pm
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; iNovember 13, 2006 at 1:47 pm
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.November 13, 2006 at 2:02 pm
[...] 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. [...]
November 13, 2006 at 2:44 pm
“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.
November 13, 2006 at 2:52 pm
No, it still doesn’t make sense.
var f = sometest() ?
function () {command1()} :
function () {command2()};
November 13, 2006 at 4:22 pm
[...] JavaScript, We Hardly new Ya » Yahoo! User Interface Blog (tags: javascript optimization) [...]
November 13, 2006 at 4:59 pm
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.
November 13, 2006 at 5:01 pm
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.
November 13, 2006 at 6:15 pm
new…
…
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.
November 13, 2006 at 10:04 pm
[...] 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. [...]
November 13, 2006 at 10:48 pm
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
November 13, 2006 at 11:59 pm
And we could have an even better code in this case with something like
var f = sometest() ?command1 :
command2;
November 14, 2006 at 1:14 am
JavaScript, We Hardly new Ya…
When to use, or rather when not to use the new operator in JavaScript…
November 14, 2006 at 7:14 am
Pretty good stuff to learn.
November 14, 2006 at 9:42 am
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.
November 14, 2006 at 11:58 am
[...] 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. [...]
November 14, 2006 at 11:20 pm
[...] JavaScript, We Hardly new Ya » Yahoo! User Interface Blog [...]
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.
November 15, 2006 at 9:40 am
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.
November 15, 2006 at 10:40 am
Thanks for this clear and instructive article. The comments are good too.
November 16, 2006 at 5:39 pm
BTW, all comments after http://yuiblog.com/blog/2006/11/13/javascript-we-hardly-new-ya/#comment-15132 are unreadable in IE.
November 16, 2006 at 10:50 pm
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!
November 17, 2006 at 7:14 am
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.
November 17, 2006 at 2:46 pm
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.
November 24, 2006 at 3:12 pm
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() {…
November 27, 2006 at 12:09 pm
“Do as I say, not as I do”
December 4, 2006 at 6:08 am
good article to me!!! i think {} is good to do use for
saving bytes! and new Function() should better not use
except peculiar instance
January 13, 2007 at 7:21 pm
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.February 16, 2007 at 11:41 am
;(sometest() ? command1 : command2)(arg1, arg2, arg3)
This coding style makes semicolons omission no longer an option.
March 20, 2007 at 6:02 am
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…….
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?
May 16, 2007 at 12:32 pm
[...] JavaScript, We Hardly new Ya » Yahoo! User Interface Blog (tags: javascript optimization performance) [...]
June 3, 2007 at 1:24 am
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.)
June 3, 2007 at 2:00 am
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
June 5, 2007 at 12:56 pm
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?
July 10, 2007 at 6:29 am
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.
November 17, 2007 at 6:36 am
[...] JavaScript, We Hardly new Ya [...]
December 20, 2008 at 9:45 am
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?
February 25, 2009 at 6:04 pm
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.
February 26, 2009 at 6:52 am
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;
March 20, 2009 at 6:00 am
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.
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).
September 22, 2009 at 12:05 am
I love this pattern but I have the same doubts Darryl Stoflet has.
February 23, 2010 at 9:57 am
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.