Crockford\'s book, JavaScript: The Good Parts, says (on page 114) that constructor functions should always be given names with an initial capital letter (i
You're stuck with using 'new' to instantiate other people's objects. But for your own code, you can avoid the pitfalls of both 'this' and 'new'.
(By the way, the issue really isn't with 'new' itself. But an object being instantiated with 'new' is probably using 'this' internally. Use of 'this' leads to frequent and subtle bugs, because javascript's 'this' requires the caller to do extra work to bind the called method to the right object, and incorrect bindings are hard to lint or otherwise detect before runtime.)
Short version:
To avoid using 'new' to instantiate objects you write, just return an object from any function. Inside that function, attach any methods to that object and do any initialization. You're done -- that function is both your class definition and constructor.
Long version, with example:
The following 'self' pattern avoids use of both 'new' and 'this'. While the pattern does store method copies in each object, this won't matter unless you're creating a lot of objects at runtime. If that's the case, then you can always use the 'flyweight' pattern from http://justjs.com/posts/this-considered-harmful. (While the examples on that page still use 'this' a little, it's a slight tweak to adapt those to the following pattern as well.)
// this function defines a "class" -- the whole function is the constructor
function Foo(x) {
// create/init whatever object type you want here
var self = {x: x};
// if subclassing, for instance, you can do:
// var self = Baz(x);
// public method
self.foo = function() {
return self.x;
};
// public method
self.bar = function() {
console.log(self.x);
logger();
};
// private method
function logger() {
console.log(self.x);
}
// ...more constructor bits can go here
// don't forget to return self
return self;
}
var f = Foo(1);
var g = Foo(2);
setTimeout(f.bar, 1000);
setTimeout(g.bar, 1000);
console.log(g.foo()); // 2
g.x = 5;
console.log(f.foo()); // 1
console.log(g.foo()); // 5
// ...then, 1 second later:
// 1 (from f.bar)
// 1 (from f.logger)
// 5 (from g.bar)
// 5 (from g.logger)
// blows up if uncommented
// f.logger();