API Docs for: 0.0.0
Show:

File: src/index.js

//     subject
//     (c) simonfan
//     subject is licensed under the MIT terms.

/**
 * Expressive prototypal inheritance.
 *
 * @module subject
 */

/* jshint ignore:start */
if (typeof define !== 'function') { var define = require('amdefine')(module) }
/* jshint ignore:end */

define(['lodash'], function (_) {
	'use strict';

	function argumentsToArray(args) {
		return Array.prototype.slice.call(args);
	}

	/**
	 * The original prototype object.
	 *
	 * @class __prototype
	 * @static
	 */
	var __prototype = {
		/**
		 * This method will be called before returning
		 * the instance. Put your initialization code here.
		 *
		 * @method initialize
		 */
		initialize: function () {},
	};

	/**
	 * Mock
	 * @class __subject
	 */
	var __subject = function () {};

	/**
	 * The prototype object.
	 * When the __subject function is run, it will
	 * create an instance of `this.prototype` and call its
	 * initialize method.
	 *
	 * @property prototype
	 * @type object
	 */
	__subject.prototype = __prototype;


	/**
	 * Augments the prototype.
	 *
	 * @method proto
	 */
	__subject.proto = function proto(first, second) {

		if (_.isObject(first)) {
			_.assign(this.prototype, first);
		} else {
			this.prototype[first] = second;
		}

		return this;
	};

	/**
	 * Define a function that when run will return an instance
	 * of its prototype object.
	 *
	 * All arguments passed to the extend method
	 * will be passed on to `this.prototype.extend` method.
	 *
	 * @method extend
	 * @param [initialize] {Function}
	 * @param protoProps {Object}
	 * @param staticProps {Object}
	 */
	__subject.extend = function extend(first, second, third) {

		var protoProps, staticProps;

		// [0] parse out the arguments
		if (_.isFunction(first)) {

			// the first argument should be used as 'initialize'

			// take care not to overwrite initialize from
			// other objects, as we might be dealing with prototypes here!
			protoProps = _.assign({}, second, {
				initialize: first
			});

			staticProps = third;

		} else if (_.isObject(first)) {

			// normal
			protoProps = first || {};
			staticProps = third;
		}

		// parent
		var parent = this;

		// [1] Declare the child variable.
		var child;

		// [2] Define the child constructor/builder function
		//     that creates an instance of the prototype object
		//     and initializes it.
		child = function builder() {
			var instance = Object.create(child.prototype);
			instance.initialize.apply(instance, arguments);

			return instance;
		};

		// [3] Static methods
		_.assign(child, parent, staticProps);

		// [4] Set the child function's prototype property
		//     to reference the `nproto`, so that the new prototype may be
		//     further extended.
		child.prototype = Object.create(parent.prototype);
		child.prototype.constructor = child;

		// [5] proto protoProps.
		child.proto(protoProps);

		// [6] reference to parent's prototype.
		child.__super__ = parent.prototype;

		return child;
	};

	return __subject.extend.bind(__subject);
});