Last active
August 29, 2015 14:02
-
-
Save jpiccari/d71e04676f2abff07794 to your computer and use it in GitHub Desktop.
Factory for creating constructors that don't require new keywords with minimal boilerplate.
This file contains hidden or 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
/** | |
* Factory to take some of the boilerplate out of creating constructors | |
* which instantiate objects even without the new keyword. | |
* @param {function} fn - Input function to create constructor from. | |
* @returns The updated constructor. | |
*/ | |
function constructorFactory(fn) { | |
if (typeof fn !== 'function') { | |
throw new TypeError('Expected function!'); | |
} | |
function Constructor() { | |
var instance = Object.create(fn.prototype); | |
return fn.apply(instance, arguments) || instance; | |
} | |
Constructor.prototype = fn.prototype; | |
return Constructor; | |
} |
This file contains hidden or 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
/* | |
* There is one main pitfall to using this factory—maintaining the prototype. | |
* The function passed to the factory and the resulting constructor must have | |
* their prototypes kept in sync in order for proper prototypes to be assigned | |
* to the instantiated objects. | |
* | |
* This is avoided by either defining the function and prototype first, then | |
* reassigning the function identifier to the resulting constructor. Or by | |
* avoiding the wholesale reassignment of the prototype of either the original | |
* function or the resulting prototype. | |
*/ | |
// Example of defining the prototype first then reassigning the identifier. | |
function Shape(x, y) { | |
this.x = x; | |
this.y = y; | |
} | |
Shape.prototype = { | |
move: function(x, y) { | |
this.x += x; | |
this.y += y; | |
} | |
}; | |
// Now we can redefine Shape to the result of our constructorFactory() | |
var Shape = constructorFactory(Shape), | |
square = Shape(40, 2); | |
// Example of calling the factory and then defining the properties or methods | |
// individually after the fact. | |
var Person = constructorFactory(function(name) { | |
this.name = name; | |
}); | |
Person.prototype.introduceYourself = function() { | |
return 'Hi, my name is ' + this.name; | |
}; | |
var bob = Person('Bob'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment