public
Last active

Advanced JavaScript (ECMAScript 5) Inheritance

  • Download Gist
examples.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
var A = Function.inherit(function () {
console.log('construct A');
}, {
'aa': function () {
console.log('aa A');
},
});
 
var B = A.inherit(function () {
console.log('construct B');
}, {
'aa': function () {
console.log('aa B');
this.$super();
},
});
 
 
var b = new B();
// construct A
// construct B
b.aa();
// aa B
// aa A
 
 
var C = A.inherit({
'aa': function () {
console.log('aa C');
},
});
 
var c = new C();
// construct A
c.aa();
// aa C
 
C.prototype.aa = function () {
// this.$super is not available here
// You need to put methods that require this.$super to the initial prototype
};
function.inherit.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
(function () {
 
Object.defineProperty(Function.prototype, 'initializing', {
value: false,
writable: true,
});
Object.defineProperty(Function.prototype, '$super', {
value: function () {
throw new Error('The $super method is not available.');
},
writable: true,
});
 
Function.prototype.inherit = function (init, props) {
if (arguments.length === 1 && typeof init !== 'function') {
props = arguments[0];
init = undefined;
}
props = props || {};
 
var parent = this,
prototype;
try {
this.initializing = true;
prototype = new this();
this.initializing = false;
} catch (exc) {
throw new Error('Not possible to inherit from this function');
}
 
var createChildMethod = function (key, fn) {
return function () {
var tmp = this.$super,
_parent = parent.prototype,
_super;
do {
_super = _parent;
if (_parent.constructor === Object) {
break;
}
_parent = Object.getPrototypeOf(_parent);
} while (_super[key] === undefined);
if (_super[key] !== undefined) {
this.$super = _super[key];
}
var res = fn.apply(this, Array.prototype.slice.call(arguments));
this.$super = tmp;
return res;
};
};
Object.getOwnPropertyNames(props).forEach(function (key) {
if (typeof props[key] === 'function') {
prototype[key] = createChildMethod(key, props[key]);
} else {
var desc = Object.getOwnPropertyDescriptor(prototype, key);
if (desc === undefined || desc.configurable) {
Object.defineProperty(prototype, key, Object.getOwnPropertyDescriptor(props, key));
}
}
});
 
var Function = function () {
if (!this.initializing) {
var args = Array.prototype.slice.call(arguments);
if (parent !== window.Function) {
parent.apply(this, args);
}
if (typeof init === 'function') {
init.apply(this, args);
}
}
};
 
var skip = Object.getOwnPropertyNames(function () {}).concat(['__children__']);
Object.getOwnPropertyNames(parent).forEach(function (key) {
if (skip.indexOf(key) === -1) {
Object.defineProperty(this, key, Object.getOwnPropertyDescriptor(parent, key));
}
}, Function);
 
Function.prototype = prototype;
prototype.constructor = Function;
 
if (Object.getOwnPropertyDescriptor(this, '__children__') === undefined) {
Object.defineProperty(this, '__children__', {
value: [],
});
}
this.__children__.push(Function);
 
return Function;
};
 
Function.prototype.getChildFunctions = function () {
return (this.__children__ !== undefined) ? this.__children__.slice() : [];
};
 
}());

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.