Source: modules/base/module.js

  1. /**
  2. * Module provides methods to create a new module. Any module created here has
  3. * the ability of being extended by other modules. Existing properties are
  4. * overridden.
  5. *
  6. * Creating a module
  7. * @example
  8. * var NewModule = Module.create(function() {
  9. * this.value = 100;
  10. * });
  11. * NewModule.prototype.print = function() { console.log(this.value); };
  12. *
  13. * var instance = NewModule();
  14. * instance.print(); // 100
  15. *
  16. * Extending a module
  17. * @example
  18. * var AnotherModule = Module.create();
  19. * AnotherModule.prototype.inc = function() { this.value++; };
  20. * var ExtendingModule = NewModule.extend(AnotherModule);
  21. *
  22. * var instance = ExtendingModule();
  23. * instance.inc();
  24. * instance.print(); // 101
  25. *
  26. * @module modules/base/module
  27. */
  28. define(function() {
  29. 'use strict';
  30. const LOG_LEVEL = {
  31. NONE: 0,
  32. DEBUG: 1,
  33. INFO: 2,
  34. WARN: 3,
  35. ERROR: 4,
  36. ALL: 5
  37. };
  38. var _constructorMap = (function() {
  39. var _ctorMap = new Map();
  40. var _getConstructor = function(Module) {
  41. return _ctorMap.get(Module) || function() {};
  42. };
  43. var _registerConstructor = function(Module, constructor) {
  44. _ctorMap.set(Module, constructor || function() {});
  45. };
  46. return {
  47. getConstructor: _getConstructor,
  48. registerConstructor: _registerConstructor
  49. };
  50. })();
  51. var _emptyFunction = function() {};
  52. var _createLogger = function(name) {
  53. switch (name) {
  54. case 'DEBUG':
  55. return function(msg) {
  56. console.log(this._msgPrefix + msg);
  57. };
  58. case 'INFO':
  59. return function(msg) {
  60. console.info(this._msgPrefix + msg);
  61. };
  62. case 'WARN':
  63. return function(msg) {
  64. console.warn(this._msgPrefix + msg);
  65. };
  66. case 'ERROR':
  67. return function(msg) {
  68. console.error(this._msgPrefix + msg);
  69. };
  70. }
  71. };
  72. var ModulePrototype = {
  73. get _msgPrefix() {
  74. return '[' + this.$name + ']: ';
  75. },
  76. debug: _emptyFunction,
  77. info: _emptyFunction,
  78. warn: _emptyFunction,
  79. error: _emptyFunction,
  80. throw: function(msg) {
  81. throw new Error(this._msgPrefix + msg);
  82. },
  83. set _logLevel(value) {
  84. Object.keys(LOG_LEVEL).forEach((name) => {
  85. var level = LOG_LEVEL[name];
  86. if (value >= level && value > 0) {
  87. this[name.toLowerCase()] = _createLogger(name);
  88. }
  89. });
  90. },
  91. super: _constructorMap.getConstructor
  92. };
  93. var _extend = function() {
  94. switch (arguments.length) {
  95. case 0:
  96. break;
  97. case 1:
  98. var Module = arguments[0];
  99. for (var prop in Module.prototype) {
  100. if (prop === '$name') {
  101. continue;
  102. }
  103. var pd = Object.getOwnPropertyDescriptor(Module.prototype, prop);
  104. if (pd) {
  105. Object.defineProperty(this.prototype, prop, pd);
  106. }
  107. }
  108. break;
  109. default:
  110. Array.prototype.forEach.call(arguments, (Module) => {
  111. _extend.call(this, Module);
  112. });
  113. break;
  114. }
  115. return this;
  116. };
  117. // Returns a module function. The function returns an instance of the
  118. // module when it is called. The passed constructor is called using the
  119. // instance as "this".
  120. function _create(constructor) {
  121. if (constructor && typeof constructor !== 'function') {
  122. throw new Error('[Module]: Invalid constructor');
  123. }
  124. var ModuleFunc = function() {};
  125. ModuleFunc.prototype = Object.create(ModulePrototype);
  126. ModuleFunc.prototype.$name = constructor && constructor.name || '';
  127. var Module = function() {
  128. var instance = new ModuleFunc();
  129. if (constructor) {
  130. constructor.apply(instance, arguments);
  131. }
  132. return instance;
  133. };
  134. _constructorMap.registerConstructor(Module, constructor);
  135. Module.extend = _extend;
  136. Module.prototype = ModuleFunc.prototype;
  137. return Module;
  138. }
  139. return {
  140. LOG_LEVEL: LOG_LEVEL,
  141. create: _create
  142. };
  143. });