(function (module) { 'use strict'; var privateStaticVariable = 1; function Computer() { var privateVariable = 5; this.publicVariable = 8; Computer.publicStaticVariable = 1; this.getAnswer = function () { return privateStaticVariable + Computer.publicStaticVariable + this.publicVariable * privateVariable ; }; } module.exports = Computer; }(module));
Eval is evil!But oddly enough, the latter was the best (in its subjective opinion) of all those considered according to the following criteria:
(function () { /** * Inject protected-data object to class * @private * @param Class {Function} Class * @param protectedData {Object} Protected-data object * @return {Function} Result class */ function injectProtected(Class, protectedData) { return (function (Native) { function Overridden() { var args = Array.prototype.map.call(arguments, function (value) { return [value]; }); args.unshift(protectedData); args.unshift(null); return (new (Function.prototype.bind.apply(Native, args))()); } Overridden.prototype = new Native({}); return Overridden; }(Class)); } }());
(function (Function) { 'use strict'; /** * Check if protected-data was injected * @returns {boolean} */ Function.prototype.isProtectedInjected = function () { return false; }; /** * Inject protected-data object to class * @private * @param Class {Function} Class * @param protectedData {Object} Protected-data object * @return {Function} Result class */ function injectProtected(Class, protectedData) { return (function (Native) { function Overridden() { var args = Array.prototype.map.call(arguments, function (value) { return [value]; }); args.unshift(protectedData); args.unshift(null); return (new (Function.prototype.bind.apply(Native, args))()); } Overridden.prototype = new Native({}); Overridden.getNative = function () { return Native; }; Overridden.isProtectedInjected = function () { return true; }; return Overridden; }(Class)); } /** * Get native class without injection of protected * @returns {Function} Class */ Function.prototype.getNative = function () { return this; }; /** * Extend from @a ParentClass * @param {Function} ParentClass * @return {Function} Result class */ Function.prototype.extend = function (ParentClass) { var protectedData = {}, parent, me = this.getNative(); if (ParentClass.isProtectedInjected()) { ParentClass = injectProtected(ParentClass.getNative(), protectedData); } parent = new ParentClass(); me.prototype = parent; me.prototype.constructor = me; protectedData.parent = parent; if (me.isProtectedInjected()) { me = injectProtected(me, protectedData); } me.prototype = parent; me.prototype.constructor = me; return me; }; /** * Injects protected-data object to class * @example * function SomeClass(protectedData/\* , ... *\/) { * protectedData.protectedMethod = function () {}; * protectedData.protectedVariable = 'Access only from children and self'; * /\* ...Realization... *\/ * }.injectProtected() * @returns {Function} */ Function.prototype.injectProtected = function () { return injectProtected(this, {}); }; }(Function));
(function (module) { 'use strict'; var privateStaticVariable = 1; function Computer(protectedData) { var privateVariable = 5; this.publicVariable = 8; protectedData.badModifier = 0.1; Computer.publicStaticVariable = 1; this.getAnswer = function () { return ( privateStaticVariable + Computer.publicStaticVariable + this.publicVariable * privateVariable ) * protectedData.badModifier; }; } module.exports = Computer.injectProtected(); // <- That's it! }(module));
(function (module) { 'use strict'; var Computer = require('Computer'); function FixedComputer(protectedData) { Computer.call(this); // Super analogue protectedData.badModifier = 1; } module.exports = FixedComputer.injectProtected().extend(Computer); // <- That's it! }(module));
Source: https://habr.com/ru/post/251649/
All Articles