objectUtils.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. const { clone, cloneDeep } = require('./clone');
  2. function isObject(value) {
  3. return value !== null && typeof value === 'object';
  4. }
  5. // Quick and dirty check if an object is a plain object and not
  6. // for example an instance of some class.
  7. function isPlainObject(value) {
  8. return (
  9. isObject(value) &&
  10. (!value.constructor || value.constructor === Object) &&
  11. (!value.toString || value.toString === Object.prototype.toString)
  12. );
  13. }
  14. function isFunction(value) {
  15. return typeof value === 'function';
  16. }
  17. function isString(value) {
  18. return typeof value === 'string';
  19. }
  20. function asArray(value) {
  21. return Array.isArray(value) ? value : [value];
  22. }
  23. function uniqBy(items, keyGetter = null) {
  24. const map = new Map();
  25. for (let i = 0, l = items.length; i < l; ++i) {
  26. const item = items[i];
  27. const key = keyGetter !== null ? keyGetter(item) : item;
  28. map.set(key, item);
  29. }
  30. return Array.from(map.values());
  31. }
  32. function omit(obj, keysToOmit) {
  33. keysToOmit = asArray(keysToOmit);
  34. const keys = Object.keys(obj);
  35. const out = {};
  36. for (let i = 0, l = keys.length; i < l; ++i) {
  37. const key = keys[i];
  38. if (!keysToOmit.includes(key)) {
  39. out[key] = obj[key];
  40. }
  41. }
  42. return out;
  43. }
  44. function difference(arr1, arr2) {
  45. const arr2Set = new Set(arr2);
  46. const diff = [];
  47. for (let i = 0; i < arr1.length; ++i) {
  48. const value = arr1[i];
  49. if (!arr2Set.has(value)) {
  50. diff.push(value);
  51. }
  52. }
  53. return diff;
  54. }
  55. function union(arr1, arr2) {
  56. const all = new Set();
  57. for (let i = 0; i < arr1.length; ++i) {
  58. all.add(arr1[i]);
  59. }
  60. for (let i = 0; i < arr2.length; ++i) {
  61. all.add(arr2[i]);
  62. }
  63. return Array.from(all);
  64. }
  65. function last(arr) {
  66. return arr[arr.length - 1];
  67. }
  68. function upperFirst(str) {
  69. return str[0].toUpperCase() + str.substring(1);
  70. }
  71. function values(obj) {
  72. if (isObject(obj)) {
  73. const keys = Object.keys(obj);
  74. const values = new Array(keys.length);
  75. for (let i = 0, l = keys.length; i < l; ++i) {
  76. values[i] = obj[keys[i]];
  77. }
  78. return values;
  79. } else {
  80. return [];
  81. }
  82. }
  83. function once(func) {
  84. let called = false;
  85. let value = undefined;
  86. return function() {
  87. if (called === false) {
  88. called = true;
  89. value = func.apply(this, arguments);
  90. }
  91. return value;
  92. };
  93. }
  94. function flatten(arrays) {
  95. const out = [];
  96. let outIdx = 0;
  97. for (let i = 0, l = arrays.length; i < l; ++i) {
  98. const value = arrays[i];
  99. if (Array.isArray(value)) {
  100. for (let j = 0; j < value.length; ++j) {
  101. out.push(value[j]);
  102. }
  103. } else {
  104. out.push(value);
  105. }
  106. }
  107. return out;
  108. }
  109. function get(obj, path) {
  110. for (let i = 0, l = path.length; i < l; ++i) {
  111. const key = path[i];
  112. if (!isObject(obj)) {
  113. return undefined;
  114. }
  115. obj = obj[key];
  116. }
  117. return obj;
  118. }
  119. function set(obj, path, value) {
  120. const inputObj = obj;
  121. for (let i = 0, l = path.length - 1; i < l; ++i) {
  122. const key = path[i];
  123. let child = obj[key];
  124. if (!isObject(child)) {
  125. const nextKey = path[i + 1];
  126. if (isNaN(nextKey)) {
  127. child = {};
  128. } else {
  129. child = [];
  130. }
  131. obj[key] = child;
  132. }
  133. obj = child;
  134. }
  135. if (path.length > 0 && isObject(obj)) {
  136. obj[path[path.length - 1]] = value;
  137. }
  138. return inputObj;
  139. }
  140. function zipObject(keys, values) {
  141. const out = {};
  142. for (let i = 0, l = keys.length; i < l; ++i) {
  143. out[keys[i]] = values[i];
  144. }
  145. return out;
  146. }
  147. function chunk(arr, chunkSize) {
  148. const out = [];
  149. for (let i = 0, l = arr.length; i < l; ++i) {
  150. const item = arr[i];
  151. if (out.length === 0 || out[out.length - 1].length === chunkSize) {
  152. out.push([]);
  153. }
  154. out[out.length - 1].push(item);
  155. }
  156. return out;
  157. }
  158. module.exports = {
  159. isString,
  160. isObject,
  161. isFunction,
  162. isPlainObject,
  163. difference,
  164. upperFirst,
  165. zipObject,
  166. cloneDeep,
  167. asArray,
  168. flatten,
  169. uniqBy,
  170. values,
  171. union,
  172. chunk,
  173. clone,
  174. omit,
  175. once,
  176. last,
  177. get,
  178. set
  179. };