Skip to content

Instantly share code, notes, and snippets.

@Skateside
Last active October 14, 2015 01:08
Show Gist options
  • Save Skateside/4284435 to your computer and use it in GitHub Desktop.
Save Skateside/4284435 to your computer and use it in GitHub Desktop.
Just a simpler version of SK80.create from the mixin micro library. Note to self: integrate this
/**
* Extends one object with another. The object in the first argument is
* modified.
*
* @param {Object} source Source object to extend.
* @param {Object} extra Additional properties to add to the source object.
* @return {Object} Modified source object.
*/
function extendObject(source, extra) {
var prop = '',
owns = Object.prototype.hasOwnProperty;
for (prop in extra) {
if (owns.call(extra, prop)) {
source[prop] = extra[prop];
}
}
return source;
}
/**
* Creates a new class, possibly based on an old one.
*
* @param {Function=} Base Optional base class that the new one will inherit
* from.
* @param {Object} config Static configuration for the new class.
* @param {Object} proto Methods and properties to be added to the new class'
* prototype.
* @return {Function} New class constructor.
*/
function createClass(Base, config, proto) {
/**
* Base function for the new class. All new classes push everything into an
* init method.
*
* @constructor
*/
function F() {
this.init.apply(this, arguments);
}
/**
* Empty function so a constructor function isn't called when inheriting.
*
* @constructor
*/
function B() {}
// Allow the Base to be optional.
if (!proto) {
proto = config;
config = Base;
Base = Object;
}
// Add static properties for the parent and the config.
F.config = config;
F.parent = Base.prototype;
// Inherit from Base.
B.prototype = Base.prototype;
F.prototype = new B();
// Add the new properties.
extendObject(F.prototype, proto);
F.prototype.constructor = F;
// Return the constructor.
return F;
}
// Example uses:
var Person = createClass({
TXT_FOO: 'foo'
},
{
init: function (name) {
this.name = name + ' ' + Person.config.TXT_FOO;
},
getName: function () {
return this.name;
}
});
var Writer = createClass(Person, {}, {
init: function (name, books) {
Writer.parent.init.call(this, name);
this.books = books;
},
getBooks: function () {
return this.books;
}
});
var Celeb = createClass(Writer, {}, {
init: function (name, books, fame) {
Celeb.parent.init.call(this, name, books);
this.fame = fame;
},
getFame: function () {
return this.fame;
}
});
var person = new Person('a');
var writer = new Writer('c', 'd');
var celeb = new Celeb('e', 'f', 'g');
var FOO = {};
(function (foo) {
'use strict';
var constants = {
PROP_PROTO: '$proto'
},
hasOwn = Object.prototype.hasOwnProperty,
toString = Object.prototype.toString,
undef; // = undefined;
// Checks to ensure that a given object is a Function.
//
// Takes:
// object (Mixed) The object to check.
// Returns:
// (Boolean) true if a Function, false otherwise.
function isFunction(object) {
return toString.call(object) === '[object Function]';
}
// Works out whether a given object is the global window object.
// Based on jQuery.isWindow http://code.jquery.com/jquery-1.8.3.js
//
// Takes:
// object (Mixed) The object to test.
// Returns:
// (Boolean) true if the object is window, false otherwise.
function isWindow(object) {
return object !== null && object !== undef && object === object.window;
}
// Checks an object to see if it's a plain object, rather than something like a
// DOM node or window.
// Based on jQuery.isPlainObject http://code.jquery.com/jquery-1.8.3.js
//
// Takes:
// object (Mixed) The object to test.
// Returns:
// (Boolean) true if the object is a plain object, false
// otherwise.
function isPlainObject(object) {
var isPlain = false,
key;
if (object && typeof object === 'object' && !Array.isArray(object) &&
!object.nodeType && !isWindow(object)) {
for (key in object) {
}
isPlain = key === undef || hasOwn.call(object, key);
}
return isPlain;
}
// Extends source by going through the properties of extra and adding them to
// source. If the property of source and extra are both plain objects, those
// objects are also enhanced.
//
// Takes:
// source (Object) The source object that should be enhanced.
// extras (Object) Object with properties that should be added to
// source.
// Returns:
// (Object) The extended source.
function extend(source, extras) {
var prop;
for (prop in extras) {
if (extras.hasOwnProperty(prop)) {
if (isPlainObject(source[prop]) &&
isPlainObject(extras[prop])) {
source[prop] = extend({}, source[prop]);
source[prop] = extend(source[prop], extras[prop]);
} else {
source[prop] = extras[prop];
}
}
}
return source;
}
// Expose the extend function.
foo.extend = extend;
// Creates an object based on another. The link is live so changes in the parent
// object are reflected in the child. Optionally, an object may be passed in
// containing a series of properties to add to the created object and arguments
// may be passed in to trigger the created object's "init" method.
//
// Takes:
// base (Object) The base object from which the new one should be
// made.
// [extras] (Object) Extra properties to add to the new object.
// [args] (Array) Arguments to be passed to an "init" method of
// the new object.
// Returns:
// (Object) The newly created object.
foo.create = function (base, extras, args) {
var created = Object.create(base);
if (Array.isArray(extras)) {
args = extras;
extras = null;
}
if (isPlainObject(extras)) {
extend(created, extras);
created[constants.PROP_PROTO] = base;
}
if (Array.isArray(args) && isFunction(created.init)) {
created.init.apply(created, args);
}
return created;
};
}(FOO));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment