Object.extend Black Magic
Just an interesting inheritance mixin I use from time to time. Haven't seen it around on the web,
thought you might enjoy it.
function extend () {
return [].reduce.call(arguments, Object.create, this);
}
Create yourself a prototype and add in the ye olde extend magic.
Let's just use the classic example of person/say name we all know and love.
var person = {
sayName: function () {
console.log("Hello, my name is " + this.name);
return this;
},
name: "John Doe",
extend: extend
};
Now let's create another "prototype", but not too specific. Just add in some extra functionality.
Note this is formatting using Object.create's propertiesObject argument.
var ninja = {
hide: {
value: function () {
this.hidden = true;
return this;
}
}
};
Maybe another for good measure? Be sure to note here that these don't inherit from person, it's just some behavior or data we might want to add to a person.
var wizard = {
fireball: {
value: function () {
console.log("Pew Pew!");
return this;
}
}
};
And now: a god-damned ninja-wizard.
var ninjaWizard = person.extend(ninja, wizard, {
name: {
value: "Ninja Wizard"
},
wtf: {
value: function () {
console.log("RWAWRRRGGGGG!");
return this;
}
}
});
ninjaWizard.sayName().wtf().fireball().hide();
Maybe create a son of Ninja Wizard?
var shaggar = ninjaWizard.extend({
name: {
value: "Shaggar, Son of Dolff"
},
feedToGoats: {
value: function () {
if (this.hasCutoffManhood) {
//Do things
}
}
}
});
shaggar.sayName().feedToGoats();
The above works with as many prototypes as you'd like to throw at it. If you want to do a little
formatting to avoid the verbosity of Object.create, go for it. I personally don't mind it.
EDIT: For those of you interested, I've created a very small library with this functionality: metatype.js.
Written by Chris Coniglio
Related protips
7 Responses

Tags: "wizards", "ninjas". Niiiice.

This is pretty sick, nice trick

hi chris, that looks great. does it have any disatvangtes compared to the standard extend method (like underscore's)?

Awesome!!!

This should be in standard.

Hey @oronm, this is a very different type of functionality than underscore's extend. The extend in underscore simply copies properties from one object to another. This is creating a new object in which the prototype chain extends from the object on which the method was called, includes each argument passed, and ends with the new object.

"a god-damned ninja-wizard" code that is :)
Awesome tip!