rewritten with descriptive names
Crockford's naming obfuscates things a bit, so here's the same functionality:
Function.prototype.new = function ( ) {
var theRealConstructor = this;
var freshObj = Object.create(theRealConstructor.prototype);
var freshObj_after_theRealConstructor =
theRealConstructor.apply(freshObj, arguments);
if(typeof freshObj_after_theRealConstructor === 'object'){
return freshObj_after_theRealConstructor;
} else {
return freshObj;
}
};
which hopefully is clearer than this
, other
, and that
.
Elaboration and example:
// this is a Waffle constructor
function Waffle(topping,ingredients){
this.toppings = topping;
this.ingredients = ['batter','eggs','sugar'].concat(ingredients);
}
// make the .new method available to all functions
// including our waffle constructor, `Waffle`
Function.prototype.new = function(){
// inside `Waffle.new`, the `this` will be
// `Waffle`, the actual constructor that we want to use
var theRealConstructor = this;
// now we create a new object, a fresh waffle,
// that inherits from the prototype of `Waffle`
var freshObj = Object.create(theRealConstructor.prototype);
// and call `Waffle` with it's `this` set to
// our fresh waffle; that's what we want the ingredients added to
var freshObj_after_theRealConstructor =
theRealConstructor.apply(freshObj, arguments);
// If we managed to make an object, return it!
if(typeof freshObj_after_theRealConstructor === 'object'){
return freshObj_after_theRealConstructor;
// otherwise, just return the pre-constructor fresh waffle
} else {
return freshObj;
}
};
// And to try it out
var myBreakfast = Waffle.new('syrup',['blueberries','chocolate']);
// and `myBreakfast` would look look like ↓↓
// {
// toppings: "syrup",
// ingredients:[
// "batter",
// "eggs",
// "sugar",
// "blueberries",
// "chocolate"
// ]
// }