Created
October 19, 2014 03:14
-
-
Save RomanGorbatko/e820597cb77d4dec202e to your computer and use it in GitHub Desktop.
SS86.js
This file contains 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
var SS86 = function() {}; | |
SS86.extend = function(_instance, _static) { // subclass | |
"use strict"; | |
var extend = SS86.prototype.extend; | |
// build the prototype | |
SS86._prototyping = true; | |
var proto = new this(); | |
extend.call(proto, _instance); | |
proto.SS86 = function() { | |
// call this method from any other method to invoke that method's ancestor | |
}; | |
delete SS86._prototyping; | |
// create the wrapper for the constructor function | |
//var constructor = proto.constructor.valueOf(); //-dean | |
var constructor = proto.constructor; | |
var klass = proto.constructor = function() { | |
if (!SS86._prototyping) { | |
if (this._constructing || this.constructor == klass) { // instantiation | |
this._constructing = true; | |
constructor.apply(this, arguments); | |
delete this._constructing; | |
} else if (arguments[0] !== null) { // casting | |
return (arguments[0].extend || extend).call(arguments[0], proto); | |
} | |
} | |
}; | |
// build the class interface | |
klass.ancestor = this; | |
klass.extend = this.extend; | |
klass.forEach = this.forEach; | |
klass.implement = this.implement; | |
klass.prototype = proto; | |
klass.toString = this.toString; | |
klass.valueOf = function(type) { | |
//return (type == "object") ? klass : constructor; //-dean | |
return (type == "object") ? klass : constructor.valueOf(); | |
}; | |
extend.call(klass, _static); | |
// class initialisation | |
if (typeof klass.init == "function") klass.init(); | |
return klass; | |
}; | |
SS86.prototype = { | |
extend: function(source, value) { | |
if (arguments.length > 1) { // extending with a name/value pair | |
var ancestor = this[source]; | |
if (ancestor && (typeof value == "function") && // overriding a method? | |
// the valueOf() comparison is to avoid circular references | |
(!ancestor.valueOf || ancestor.valueOf() != value.valueOf()) && | |
/\bSS86\b/.test(value)) { | |
// get the underlying method | |
var method = value.valueOf(); | |
// override | |
value = function() { | |
var previous = this.SS86 || SS86.prototype.SS86; | |
this.SS86 = ancestor; | |
var returnValue = method.apply(this, arguments); | |
this.SS86 = previous; | |
return returnValue; | |
}; | |
// point to the underlying method | |
value.valueOf = function(type) { | |
return (type == "object") ? value : method; | |
}; | |
value.toString = SS86.toString; | |
} | |
this[source] = value; | |
} else if (source) { // extending with an object literal | |
var extend = SS86.prototype.extend; | |
// if this object has a customised extend method then use it | |
if (!SS86._prototyping && typeof this != "function") { | |
extend = this.extend || extend; | |
} | |
var proto = {toSource: null}; | |
// do the "toString" and other methods manually | |
var hidden = ["constructor", "toString", "valueOf"]; | |
// if we are prototyping then include the constructor | |
var i = SS86._prototyping ? 0 : 1; | |
while (key = hidden[i++]) { | |
if (source[key] != proto[key]) { | |
extend.call(this, key, source[key]); | |
} | |
} | |
// copy each of the source object's properties to this object | |
for (var key in source) { | |
if (!proto[key]) extend.call(this, key, source[key]); | |
} | |
} | |
return this; | |
} | |
}; | |
SS86 = SS86.extend({ | |
constructor: function() { | |
this.extend(arguments[0]); | |
} | |
}, { | |
ancestor: Object, | |
version: "1.1", | |
forEach: function(object, block, context) { | |
for (var key in object) { | |
if (this.prototype[key] === undefined) { | |
block.call(context, object[key], key, object); | |
} | |
} | |
}, | |
implement: function() { | |
for (var i = 0; i < arguments.length; i++) { | |
if (typeof arguments[i] == "function") { | |
// if it's a function, call it | |
arguments[i](this.prototype); | |
} else { | |
// add the interface using the extend method | |
this.prototype.extend(arguments[i]); | |
} | |
} | |
return this; | |
}, | |
toString: function() { | |
return String(this.valueOf()); | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment