Skip to content

Instantly share code, notes, and snippets.

@ahomu
Last active December 16, 2015 17:50
Show Gist options
  • Save ahomu/5473423 to your computer and use it in GitHub Desktop.
Save ahomu/5473423 to your computer and use it in GitHub Desktop.
継承脳乙
'use strict'
var DEFINE_NOT_WRITABLE = {writable: false};
/**
* Base Class of OOP feature
*
// e.g 1
var Klass = klass.of({
constructor: function() {
console.log('Hello World');
},
foo: 'bar',
baz: 'qux'
});
// e.g 2
function NewClass() {
console.log('This is constructor');
}
klass.of(NewClass, {
hoge: 'fuga',
hige: 'piyo'
};
*
* @abstract
* @class Klass
* @returns {*}
*/
var klass = {
mix : mix,
inherits: inherits,
of : of
};
/**
* `mix` is Helper function, extend a given object in passed object
*
* @static
* @param {*} given
* @param {*} passed
*/
function mix(given, passed) {
var i = 0, ary = Object.keys(passed), iz = ary.length, prop;
for (; i<iz; i++) {
prop = ary[i];
given[prop] = passed[prop];
}
}
/**
* `inherits` is Helper function, OOP inheritance shim
*
* @static
* @param {Object|Function} parent
* @param {Object|Function} child
* @returns {Object}
*/
function inherits(parent, child) {
var superClass, subClass, addChildMembers;
superClass = parent;
if (child.hasOwnProperty('constructor')) {
// Child has `constructor` function
subClass = child.constructor;
delete child.constructor;
addChildMembers = child;
} else if (Object.prototype.toString.call(child) === '[object Function]') {
// Child is constructive `Function`
subClass = child;
addChildMembers = child.prototype;
} else {
// Child is plain `Object`
subClass = function() {
return superClass.apply(this, arguments);
};
addChildMembers = child;
}
// Inherit static members
mix(subClass, superClass);
// Inherit(clone) super class properties & methods
subClass.prototype = Object.create(superClass.prototype);
// Specify the constructor itself
subClass.prototype.constructor = subClass;
// Add sub class properties & methods
mix(subClass.prototype, addChildMembers);
// Remember the super class
subClass.prototype.__super__ = superClass.prototype;
subClass.prototype.__super__.constructor = superClass;
/**
* Call a specific method of the parent class
var SuperClass = Klass.of({
onCreate: function() {
alert('Yup!');
}
});
var SubClass = SuperClass.extends({
onCreate: function() {
this.super('onCreate', arguments); // => alert('Yup!')
}
});
* @method super
* @param {String} methodName
* @param {Object|Arguments} args
* @type {Function}
*/
subClass.prototype.super = __super;
return subClass;
}
/**
* `of` is Helper function, to generate Object like Class with basic oop fetures
*
* @static
* @param {Function|Object} constructor_or_members
* @param {Object} [members]
*/
function of(constructor_or_members, members) {
var constructor;
if (arguments.length === 1) {
members = constructor_or_members;
} else {
constructor = constructor_or_members;
}
var Constructor = typeof constructor === 'function' ? constructor
: members.hasOwnProperty('constructor') ? members.constructor
: function() {};
delete members.constructor;
mix(Constructor.prototype, members);
/**
* By inheriting an existing class, you create a new class
var ExtendedClass = SomeClass.extends(classDefinition)
var classDefinition = {
// ...
};
* @method extends
* @param {Function|Object} constructor_or_child
* @param {Object} [child]
* @return {Object}
*/
Constructor.extends = __extends;
Object.defineProperty(Constructor, 'extends', DEFINE_NOT_WRITABLE);
/**
* Mixin the trait in the `prototype` of the class
var ExtendedClassWithTrait = SomeClass.extends(classDefinition)
.with(AsyncCallbackTrait)
.with(ObservableTrait);
var classDefinition = {
// ...
};
* @method with
* @param {Object} trait
* @return {Object}
*/
Constructor.with = __with;
Object.defineProperty(Constructor, 'with', DEFINE_NOT_WRITABLE);
/**
* Method which can be used instead of the `new` statement
var instance = Klass.create();
* @method create
* @return {Instance}
*/
Constructor.create = __create;
Object.defineProperty(Constructor, 'create', DEFINE_NOT_WRITABLE);
return Constructor;
}
function __extends(constructor_or_child, child) {
if (arguments.length === 1) {
child = constructor_or_child;
} else {
child.constructor = constructor_or_child
}
return inherits(this, child);
}
function __with(trait) {
mix(this.prototype, trait);
return this;
}
function __create() {
var instance = Object.create(this.prototype);
this.apply(instance, arguments);
return instance;
}
function __super(prop, args) {
this.__super__[prop].apply(this, args);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment