I prefer to use Daniel X. Moore's {SUPER: SYSTEM}. This is a discipline that provides benefits such as true instance variables, trait based inheritance, class hierarchies and configuration options. The example below illustrates the use of true instance variables, which I believe is the biggest advantage. If you don't need instance variables and are happy with only public or private variables then there are probably simpler systems.
function Person(I) { I = I || {}; Object.reverseMerge(I, { name: "McLovin", age: 25, homeState: "Hawaii" }); return { introduce: function() { return "Hi I'm " + I.name + " and I'm " + I.age; } }; } var fogel = Person({ age: "old enough" }); fogel.introduce(); // "Hi I'm McLovin and I'm old enough"
Wow, that's not really very useful on it's own, but take a look at adding a subclass:
function Ninja(I) { I = I || {}; Object.reverseMerge(I, { belt: "black" }); // Ninja is a subclass of person return Object.extend(Person(I), { greetChallenger: function() { return "In all my " + I.age + " years as a ninja, I've never met a challenger as worthy as you..."; } }); } var resig = Ninja({name: "John Resig"}); resig.introduce(); // "Hi I'm John Resig and I'm 25"
Another advantage is the ability to have modules and trait based inheritance.
// The Bindable module function Bindable() { var eventCallbacks = {}; return { bind: function(event, callback) { eventCallbacks[event] = eventCallbacks[event] || []; eventCallbacks[event].push(callback); }, trigger: function(event) { var callbacks = eventCallbacks[event]; if(callbacks && callbacks.length) { var self = this; callbacks.forEach(function(callback) { callback(self); }); } }, }; }
An example of having the person class include the bindable module.
function Person(I) { I = I || {}; Object.reverseMerge(I, { name: "McLovin", age: 25, homeState: "Hawaii" }); var self = { introduce: function() { return "Hi I'm " + I.name + " and I'm " + I.age; } }; // Including the Bindable module Object.extend(self, Bindable()); return self; } var person = Person(); person.bind("eat", function() { alert(person.introduce() + " and I'm eating!"); }); person.trigger("eat"); // Blasts the alert!
Disclosure: I am Daniel X. Moore and this is my {SUPER: SYSTEM}. It is the best way to define a class in JavaScript.