Last active
December 16, 2015 17:50
-
-
Save ahomu/5473423 to your computer and use it in GitHub Desktop.
継承脳乙
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'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