Better JavaScript-User Defined Objects
June 22, 2011
In my last post I had a look at how we declare namespaces in JavaScript. In that example I simply declared a function which was then accessible anywhere by simply referencing the correct namespace. Today I’m going to take a look at creating custom JavaScript objects using the same kind of namespace syntax.
(function( company, undefined ) {
company.Employee = function(name, salary) {
this.name = name;
this.salary = salary;
this.modifySalary = modifySalary;
}
function modifySalary(change) {
this.salary += change;
console.log( "Changed the salary for " + this.name );
}
}( window.company = window.company || {} ));
We want to be able to create instances of the employee object which must be located in the company namespace. (I already showed in the last post how to extend the namespace – pretty much just use the exact same syntax) Now we can easily create new instances of the employee object.
var bob = new company.Employee("bob", 5000);
var john = new company.Employee("steve", 4500);
console.log("Name - " + bob.name + ", Salary - " + bob.salary);
console.log("Name - " + john.name + ", Salary - " + john.salary);
john.modifySalary(900);
console.log("Name - " + bob.name + ", Salary - " + bob.salary);
console.log("Name - " + john.name + ", Salary - " + john.salary);
So now we can create our own objects while keeping the namespaces. Note the way I created the modifySalary function – as a private function within the namespace. If I declared it as an inline function we would create function every time a new object instance is created.
Do you have a better way of creating your own JavaScript objects? If so, I’d love to hear it.
Happy coding.
Tags: JavaScript
When I write a reference type, I define the methods on the prototype:
(function( company, undefined ) {
company.Employee = function(name, salary) {
this.name = name;
this.salary = salary;
}
company.Employee.prototype.modifySalary = function(change) {
this.salary += change;
console.log( "Changed the salary for " + this.name );
}
}( window.company = window.company || {} ));
Everything defined on the prototype is shared among all instances of that type–basically using less memory. The downside is the JavaScript engine has to perform two identifier lookups when calling the method (one on the object then one on the prototype). It's tiny performance hit (and a minuscule, almost non-existent one with today's engines), but a hit none-the-less. However, I'll pick a smaller memory footprint over a minuscule hit any day.
Thanks Jeremy. That's very interesting, but wouldn't each instance simply have a reference to that function – it's not like I'm defining the function every time I create an instance. So the memory footprint would be very small?
You are correct; it would be small. From a quick profile, I see a difference of only 4KB per instance using our two simple examples. Start turning this into a real-world example, and the difference will grow.
Other things I failed to mention yesterday:
- The engine has to create the modifySalary member per instance with the "own" approach; a one time execution cost per object creation. With the prototype approach, a cost is incurred per method execution due to the identifier lookup (but once again, today's engines practically eliminate the penalty).
- Inheritance incurs more memory cost with the "own" approach. More "own" members means more memory. With prototypes, the prototypes are chained together; so no extra memory is used for those methods (but again, method execution costs for adding yet another identifier lookup).
There are pros and cons to both approaches, and it could be said that either are correct. However, JavaScript was designed as a protypical language. When you start getting into inheritance, I believe there's only one correct approach: prototypes.
Well said