Skip to content

Instantly share code, notes, and snippets.

@cjohansen
Created April 30, 2012 06:14
Show Gist options
  • Save cjohansen/2555903 to your computer and use it in GitHub Desktop.
Save cjohansen/2555903 to your computer and use it in GitHub Desktop.
Using Object create as alternative to constructors
// Example based on the one from Isaac's inherits: https://github.com/isaacs/inherits
var animal = {
create: function (name) {
return Object.create(this, { name: { value: name, enumerable: true } });
},
alive: true,
say: function (what) {
console.log(this.name + " says " + what);
}
};
// Create an animal
var pet = animal.create("Biggles");
pet.say("D'OH!"); // "Biggles says D'OH!"
// To build the prototype chain we only want object allocation,
// no initialization, so we use Object.create rather than
// animal.create()
var dog = Object.create(animal, {
sniff: { value: function () {
this.say("sniff sniff")
},
bark: { value: function () {
this.say("woof woof")
}
};
// Create a dog
var pet = dog.create("Doug");
pet.bark(); // "Doug says woof woof"
// If you're worried about performance, you might not want to use
// native Object.create, as it's pretty slow (at least with V8 last I
// checked). Let's provide a simple shim.
// Property descriptors are very verbose, and mostly not needed.
// Given a simple property-by-property extend function we could simplify.
var create = (function () {
function F() {}
return function (object) {
F.prototype = object;
return new F();
};
}());
// Simplified
var extend = function() {
var target = {};
for (var i = 0, l = arguments.length; i < l; ++i) {
for (var prop in arguments[i]) {
if (arguments[i].hasOwnProperty(prop)) {
target[prop] = arguments[i][prop];
}
}
}
return target;
};
var animal = {
create: function (name) {
return extend(create(this), { name: name });
},
alive: true,
say: function (what) {
console.log(this.name + " says " + what);
}
};
var dog = extend(create(animal), {
sniff: function () {
this.say("sniff sniff")
},
bark: function () {
this.say("woof woof")
}
};
// This whole thing was sparked by Peter Michaux' (valid) criticism that
// constructors don't go well with map: https://gist.github.com/2552304
// The create function resembles Peter's Function.prototype.new, except
// it forgoes the constructor concept entirely. It works with map the
// same way:
// Not a constructor, so lower cased first letter
var todoView = {
create: function (options) {
return extend(create(this), { // Inheritance friendly
/* ... */
});
}
};
var todoViews = todoModels.map(todoView.create, todoView);
// We could get around passing in the this argument, but then we'd have
// to hard-code todoView.create to todoView, meaning it must be overridden
// in inheriting objects, which again means it will be really hard to
// make inheriting objects call "super" on create.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment