Created
August 27, 2013 13:38
-
-
Save emilisto/6353622 to your computer and use it in GitHub Desktop.
Some code I wrote to understand the pattern @jashkenas uses to setup the prototype chain in Backbone and Underscore.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var _ = require('underscore'); | |
function printPrototypeChain(instance, asArray) { | |
var chain = [] | |
while (instance = Object.getPrototypeOf(instance)) { | |
var name = instance.constructor.toString().match(/f.+n (.+)\(/); | |
chain.push(name && name[1]? name[1] : "(anonymous function expression)") | |
} | |
return asArray? chain : chain.join(" -> ") | |
} | |
var extend = function(protoProps, staticProps) { | |
var parent = this; | |
var child; | |
// The constructor function for the new subclass is either defined by you | |
// (the "constructor" property in your `extend` definition), or defaulted | |
// by us to simply call the parent's constructor. | |
if (protoProps && _.has(protoProps, 'constructor')) { | |
child = protoProps.constructor; | |
} else { | |
child = function(){ return parent.apply(this, arguments); }; | |
} | |
// Add static properties to the constructor function, if supplied. | |
_.extend(child, parent, staticProps); | |
// Set the prototype chain to inherit from `parent`, without calling | |
// `parent`'s constructor function. | |
var Surrogate = function Surrogate(){ this.constructor = child; }; | |
Surrogate.prototype = parent.prototype; | |
child.prototype = new Surrogate; | |
// Add prototype properties (instance properties) to the subclass, | |
// if supplied. | |
if (protoProps) _.extend(child.prototype, protoProps); | |
// Set a convenience property in case the parent's prototype is needed | |
// later. | |
child.__super__ = parent.prototype; | |
return child; | |
}; | |
var Level1 = function Level1() { | |
console.log('Level1.constructor'); | |
}; | |
Level1.extend = extend; | |
var Level2 = Level1.extend({ | |
constructor: function() { | |
Level1.prototype.constructor.call(this); | |
console.log('Level2.constructor'); | |
} | |
}); | |
var Level3 = Level2.extend({ | |
constructor: function() { | |
Level2.prototype.constructor.call(this); | |
console.log('Level3.constructor'); | |
} | |
}); | |
var Level4 = Level3.extend({ | |
constructor: function() { | |
Level3.prototype.constructor.call(this); | |
console.log('Level4.constructor'); | |
} | |
}); | |
var test = new Level4; | |
console.log(printPrototypeChain(test)); | |
console.log(test instanceof Level2); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment