object-utils

inheritance, mixins and other stuff, mainly to encapsulate objects

Version vom 30.08.2016. Aktuellste Version

Dieses Skript sollte nicht direkt installiert werden. Es handelt sich hier um eine Bibliothek für andere Skripte, welche über folgenden Befehl in den Metadaten eines Skriptes eingebunden wird // @require https://update.greatest.deepsurf.us/scripts/22752/144790/object-utils.js

  1. var LIB = LIB || {};
  2. /**
  3. *
  4. * @type {{extend, TruthyFalsy, Truthy, Falsy, emptyFunction}}
  5. */
  6. LIB.objectUtils = (function() {
  7. 'use strict';
  8. /**
  9. * Extends an object from another object through the prototype chain
  10. * @param {Object} superObj - The object to be extended
  11. * @param {Object} obj - The object extending the superObj
  12. * @return {boolean} true, if executed successfully
  13. */
  14. function _extend(superObj, obj){
  15. if (typeof superObj === 'undefined') return false;
  16. if (typeof obj === 'undefined') return false;
  17. // save properties of prototype
  18. var descriptors = {};
  19. Object.getOwnPropertyNames(obj.prototype).forEach(function(propName) {
  20. descriptors[propName] = Object.getOwnPropertyDescriptor(obj.prototype, propName);
  21. });
  22. // create new prototype
  23. obj.prototype = Object.create(superObj.prototype, descriptors);
  24. obj.prototype.constructor = obj;
  25. return true;
  26. }
  27. /**
  28. * Clones properties from one object to another.
  29. * A property only gets cloned if it does not yet exist in the target object.
  30. * @param {Object} receiver - the target object receiver the properties
  31. * @param {Object} supplier - the source object supplying the properties
  32. * @param {Array} [props] - names of the relevant properties
  33. * @return {boolean} true, if executed successfully
  34. */
  35. function _mixin(receiver, supplier, props) {
  36. if (typeof supplier === 'object') return false;
  37. if (typeof receiver === 'object') return false;
  38.  
  39. var propNames = Array.isArray(props) ? props : Object.getOwnPropertyNames(supplier);
  40. propNames.forEach(function(propName){
  41. if (!Object.prototype.hasOwnProperty.call(receiver, propName)) {
  42. var desc = Object.getOwnPropertyDescriptor(supplier, propName);
  43. if (typeof desc !== 'undefined') {
  44. Object.defineProperty(receiver, propName, desc);
  45. }
  46. }
  47. });
  48. return true;
  49. }
  50.  
  51. /**
  52. * Has an object extending a super object from their prototype objects.
  53. * @param {Object} obj - The extending object
  54. * @return {{from: extendFrom, mixWith: mixWith}}
  55. */
  56. var extend = function(obj) {
  57. /**
  58. * Clones the properties of the super object if it does not yet exists in the target object.
  59. * @param {Object} superObj - the source object supplying the properties
  60. * @param {Array} [props] - names of the relevant properties
  61. * @return {{thenWith: mixWith}}
  62. */
  63. var mixWith = function(superObj, props) {
  64. if (_mixin(obj.prototype, superObj.prototype, props)){
  65. return {
  66. thenWith : mixWith
  67. };
  68. }
  69. };
  70. /**
  71. * Extends the super object from the prototype chain
  72. * @param superObj
  73. * @return {{mixWith: mixWith}}
  74. */
  75. var extendFrom = function (superObj) {
  76. if (_extend(superObj, obj)) {
  77. return {
  78. mixWith : mixWith
  79. };
  80. }
  81. };
  82.  
  83. return {
  84. from : extendFrom,
  85. mixWith : mixWith
  86. };
  87. };
  88.  
  89. /**
  90. * Defines an object that holds a value and specific values.
  91. * In case the value is a Truthy, Falsy or undefined it is overwritten with specific values.
  92. * @param value The common value.
  93. * @param [ifTruthy] if not undefined it overwrites value when it is a Truthy
  94. * @param [ifFalsy] if not undefined it overwrites value when it is a Falsy
  95. * @param [ifUndefined] if not undefined it overwrites value when it is undefined
  96. * @returns {TruthyFalsy}
  97. * @constructor
  98. */
  99. function TruthyFalsy(value, ifTruthy, ifFalsy, ifUndefined) {
  100. if (!this instanceof TruthyFalsy) {
  101. return new TruthyFalsy(value, ifTruthy, ifFalsy, ifUndefined);
  102. }
  103. this.value = value;
  104. if (ifTruthy !== 'undefined') { this.ifTruthy = ifTruthy; }
  105. if (ifFalsy !== 'undefined') { this.ifFalsy = ifFalsy; }
  106. if (ifUndefined !== 'undefined') { this.ifUndefined = ifUndefined; }
  107. }
  108. TruthyFalsy.prototype = {
  109. constructor : TruthyFalsy,
  110. valueOf: function() {
  111. var result = this.value;
  112. if (typeof this.ifUndefined !== "undefined" && typeof result === "undefined") {
  113. result = this.ifUndefined;
  114. } else if (typeof this.ifTruthy !== "undefined" && result) {
  115. result = this.ifTruthy;
  116. } else if (typeof this.ifFalsy !== "undefined" && result) {
  117. result = this.ifFalsy;
  118. }
  119. return result;
  120. },
  121. toString: function() {
  122. return String(TruthyFalsy.prototype.valueOf.call(this));
  123. }
  124. };
  125.  
  126. function Falsy(value, ifFalsy, ifUndefined) {
  127. if (!(this instanceof Falsy)) {
  128. return new Falsy(value, ifFalsy, ifUndefined);
  129. }
  130. TruthyFalsy.call(this, value, undefined, ifFalsy, ifUndefined);
  131. }
  132. extend(Falsy).from(TruthyFalsy);
  133.  
  134. function Truthy(value, ifTruthy, ifUndefined) {
  135. if (!(this instanceof Truthy)) {
  136. return new Truthy(value, ifTruthy, ifUndefined);
  137. }
  138. TruthyFalsy.call(this, value, ifTruthy, undefined, ifUndefined);
  139. }
  140. extend(Truthy).from(TruthyFalsy);
  141.  
  142. /** placeholder for empty callbacks */
  143. function emptyFunction() {}
  144.  
  145. /**
  146. * Keeps elements assigned by an index
  147. * @param {number} [initialCapacity] - initial size of the array used to store the elements
  148. * @constructor
  149. */
  150. function Keeper(initialCapacity) {
  151. if (!(this instanceof Keeper)) {
  152. return new Keeper(initialCapacity);
  153. }
  154. var _store = new Array(initialCapacity || 16);
  155. var _pointer = 0;
  156. Object.defineProperties(this, {
  157. store: {
  158. get: function() { return _store },
  159. configurable: false, enumerable: false
  160. },
  161. pointer: {
  162. get: function() { return _pointer },
  163. configurable: false, enumerable: false
  164. }
  165. })
  166. }
  167. Keeper.prototype = {
  168. constructor: Keeper,
  169. /**
  170. * Adds a new element
  171. * @param {*|Object} item - The element to keep. Must not be type of <code>undefined</code>.
  172. * @return {number} The index (key) of the added element.<br>
  173. * <code>-1</code> if the element could not be added.
  174. */
  175. push: function(item) {
  176. if (typeof item !== 'undefined') {
  177. var index = this.pointer;
  178. this.store[index] = item;
  179. for (this.pointer = index + 1; this.pointer <= this.store.length; this.pointer++) {
  180. if (typeof this.store[pointer] === 'undefined') { break; }
  181. }
  182. if (this.pointer === this.store.length) {
  183. this.store.length *= 2;
  184. }
  185. return index;
  186. }
  187. return -1;
  188. },
  189. /**
  190. * Removes an element.
  191. * @param index The index (key) of the element to be removed.
  192. * @return {boolean} <code>true</code> if the element could be removed successfully
  193. */
  194. remove: function(index) {
  195. if (index + 1 >= this.store.length) {
  196. this.store[index] = undefined;
  197. this.pointer = index;
  198. return true;
  199. }
  200. return false;
  201. },
  202. /**
  203. * Gets the element with the specified index
  204. * @param {number} index - Index (key) of the element
  205. * @return {*|Object} the element with the specified index or <code>undefined</code>
  206. */
  207. get: function (index) {
  208. if (index + 1 <= this.store.length) {
  209. return this.store[index];
  210. }
  211. return undefined;
  212. }
  213. };
  214.  
  215. return {
  216. extend: extend,
  217. TruthyFalsy: TruthyFalsy,
  218. Truthy: Truthy,
  219. Falsy: Falsy,
  220. Keeper: Keeper,
  221. get emptyFunction() { return emptyFunction }
  222. };
  223. })();