Skip to content

Instantly share code, notes, and snippets.

@Eyal-Shalev
Last active September 30, 2015 23:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Eyal-Shalev/07785bc549fe725bdab0 to your computer and use it in GitHub Desktop.
Save Eyal-Shalev/07785bc549fe725bdab0 to your computer and use it in GitHub Desktop.
/**
* @file
* @fileOverview Provides a Factory function for creating classes and a base Class object.
* @author Eyal (github.com/Eyal-Shalev)
* @version 0.1
*/
(function () {
'use strict';
/**
* @constructor Class
* A constructor function for the Base Class Object.
*/
function Class(parent, args) {/* Base Class Constructor*/}
/**
* @var ClassProperties The properties used by the base class.
* @type {Object}
*/
var ClassProperties = {
/**
* @function
* Syntactic Sugar for Factory(constructor, this)
* @see Factory
* @return {Class}
*/
extend: {
value: function(constructor) {
return Factory(constructor, this);
}
},
/**
* @function
* Use this function from the constructor of a child class to apply this constructor on the child.
* @return {Function} The apply function of this constructor.
*/
call: {
get: function() {
return this.constructor.call.bind(this.constructor);
}
},
/**
* @function
* Use this function from the constructor of a child class to apply this constructor on the child.
* @return {Function} The apply function of this constructor.
*/
apply: {
get: function () {
return this.constructor.apply.bind(this.constructor);
}
}
};
/**
* @var ClassObject
* @type {Class}
* @class Class
*
* The Base Class Object.
*/
var ClassObject = Object.create(new Class(), ClassProperties);
/**
* @function Factory
*
*
*
* @param {Function} constructor The constructor function receives two arguments. The first is the parent class object,
* and the second is the remaining arguments array.
* @param {Object} parent
* @returns {Class} A factory object
*/
function Factory(constructor, parent) {
// If a parent isn't given, use the base class object.
if (!parent) {
parent = ClassObject;
}
/**
* @var factory
* @type {Class}
*/
var factory = Object.create(parent, {
/**
* @function
* The main functionality of the Factory object.<br />
* Creates a new Object of the class described in this.constructor
*/
create: {
value: function () {
return Object.create((new this.constructor(parent, arguments)), {
prototype: {
value: this,
writable: false
}
});
}
},
prototype: {
value: parent
},
constructor: {
value: constructor
}
});
if (parent && !(parent instanceof Class)) {
// Add the base properties to the created factory if the parent doesn't contain them.
Object.defineProperties(factory, ClassProperties);
}
return factory;
}
Object.defineProperties(Factory, {
'Class': {
value: ClassObject
}
});
// Freeze to prevent changes.
Object.freeze(ClassObject);
Object.freeze(Factory);
// Reveal to the window object.
window.Class = ClassObject;
window.Factory = Factory;
})();
@Eyal-Shalev
Copy link
Author

Examples:

var Animal = Factory(function Animal(type) {
  this.type = type;
});

var Bird = Factory(function Bird(parent) {
  parent.apply(this, ['bird']);
  this.talk = function() {
    return 'KoKo';
  }
}, Animal)

var pig = Animal.create('pig');
var pigeon = Bird.create();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment