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 can avoid "new" by returning an anonymous object and using a closure in your constructor. This also help you hide private data.
Consider:
function SomeCounter(start) {
var counter = start;
return {
getCounter : function() {
return counter;
},
increaseCounter : function() {
counter++;
}
};
}
Now to use this, all you need to do is
var myCounter = SomeCounter(5);
myCounter.increaseCounter();
console.log(myCounter.getCounter()); //should log 6
The beauty of this is that you do not need to remember to use "new", but if you do it won't hurt you.
var myCounter = new SomeCounter(5); //still works
I don't know how to avoid new Date()
or new XMLHttpRequest()
either. But I do know how to avoid using new for my own types.
First, I start with Object.create()
. This is an ES5 method, so it's not available everywhere. I add it using the es5-shim, ad then I'm ready to go.
I like the module pattern, so I start by wrapping my type in a self-executing anonymous function, var Xyz = (function() {...})()
. This means I have a private space to work without making a mess in the global namespace. I return an object with a create()
function, and a prototype
property. the create()
function is for users of my type. When they want one, they call Xyz.create()
, and get back a new, initialized object of my type. The prototype
property is available if people want to inherit.
Here's an example:
var Vehicle = (function(){
var exports = {};
exports.prototype = {};
exports.prototype.init = function() {
this.mph = 5;
};
exports.prototype.go = function() {
console.log("Going " + this.mph.toString() + " mph.");
};
exports.create = function() {
var ret = Object.create(exports.prototype);
ret.init();
return ret;
};
return exports;
})();
and inheritance looks like this:
var Car = (function () {
var exports = {};
exports.prototype = Object.create(Vehicle.prototype);
exports.prototype.init = function() {
Vehicle.prototype.init.apply(this, arguments);
this.wheels = 4;
};
exports.create = function() {
var ret = Object.create(exports.prototype);
ret.init();
return ret;
};
return exports;
})();
You can avoid new
by creating factory functions:
var today = Date.getToday();
(In case you were wondering, you can't avoid it on the factory function itself:)
Date.getToday = function() { return new Date(); };
Although I only think you should create such functions if it adds semantic value (as in the case above) or if you can default some of the constructor parameters. In other words, don't do it just to avoid using new
.