Skip to content

Instantly share code, notes, and snippets.

@jpiccari
Last active August 29, 2015 14:02
Show Gist options
  • Save jpiccari/d71e04676f2abff07794 to your computer and use it in GitHub Desktop.
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.
/**
* 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;
}
/*
* 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