function.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. import { arrayReduce } from './array';
  2. /**
  3. * Checks if given variable is function.
  4. *
  5. * @param {*} func Variable to check.
  6. * @returns {Boolean}
  7. */
  8. export function isFunction(func) {
  9. return typeof func === 'function';
  10. }
  11. /**
  12. * Creates throttle function that enforces a maximum number of times a function (`func`) can be called over time (`wait`).
  13. *
  14. * @param {Function} func Function to invoke.
  15. * @param {Number} wait Delay in miliseconds.
  16. * @returns {Function}
  17. */
  18. export function throttle(func) {
  19. var wait = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 200;
  20. var lastCalled = 0;
  21. var result = {
  22. lastCallThrottled: true
  23. };
  24. var lastTimer = null;
  25. function _throttle() {
  26. var _this = this;
  27. var args = arguments;
  28. var stamp = Date.now();
  29. var needCall = false;
  30. result.lastCallThrottled = true;
  31. if (!lastCalled) {
  32. lastCalled = stamp;
  33. needCall = true;
  34. }
  35. var remaining = wait - (stamp - lastCalled);
  36. if (needCall) {
  37. result.lastCallThrottled = false;
  38. func.apply(this, args);
  39. } else {
  40. if (lastTimer) {
  41. clearTimeout(lastTimer);
  42. }
  43. lastTimer = setTimeout(function () {
  44. result.lastCallThrottled = false;
  45. func.apply(_this, args);
  46. lastCalled = 0;
  47. lastTimer = void 0;
  48. }, remaining);
  49. }
  50. return result;
  51. }
  52. return _throttle;
  53. }
  54. /**
  55. * Creates throttle function that enforces a maximum number of times a function (`func`) can be called over
  56. * time (`wait`) after specified hits.
  57. *
  58. * @param {Function} func Function to invoke.
  59. * @param {Number} wait Delay in miliseconds.
  60. * @param {Number} hits Number of hits after throttling will be applied.
  61. * @returns {Function}
  62. */
  63. export function throttleAfterHits(func) {
  64. var wait = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 200;
  65. var hits = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 10;
  66. var funcThrottle = throttle(func, wait);
  67. var remainHits = hits;
  68. function _clearHits() {
  69. remainHits = hits;
  70. }
  71. function _throttleAfterHits() {
  72. if (remainHits) {
  73. remainHits--;
  74. return func.apply(this, arguments);
  75. }
  76. return funcThrottle.apply(this, arguments);
  77. }
  78. _throttleAfterHits.clearHits = _clearHits;
  79. return _throttleAfterHits;
  80. }
  81. /**
  82. * Creates debounce function that enforces a function (`func`) not be called again until a certain amount of time (`wait`)
  83. * has passed without it being called.
  84. *
  85. * @param {Function} func Function to invoke.
  86. * @param {Number} wait Delay in milliseconds.
  87. * @returns {Function}
  88. */
  89. export function debounce(func) {
  90. var wait = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 200;
  91. var lastTimer = null;
  92. var result = void 0;
  93. function _debounce() {
  94. var _this2 = this;
  95. var args = arguments;
  96. if (lastTimer) {
  97. clearTimeout(lastTimer);
  98. }
  99. lastTimer = setTimeout(function () {
  100. result = func.apply(_this2, args);
  101. }, wait);
  102. return result;
  103. }
  104. return _debounce;
  105. }
  106. /**
  107. * Creates the function that returns the result of calling the given functions. Result of the first function is passed to
  108. * the second as an argument and so on. Only first function in the chain can handle multiple arguments.
  109. *
  110. * @param {Function} functions Functions to compose.
  111. * @returns {Function}
  112. */
  113. export function pipe() {
  114. for (var _len = arguments.length, functions = Array(_len), _key = 0; _key < _len; _key++) {
  115. functions[_key] = arguments[_key];
  116. }
  117. var firstFunc = functions[0],
  118. restFunc = functions.slice(1);
  119. return function _pipe() {
  120. return arrayReduce(restFunc, function (acc, fn) {
  121. return fn(acc);
  122. }, firstFunc.apply(this, arguments));
  123. };
  124. }
  125. /**
  126. * Creates the function that returns the function with cached arguments.
  127. *
  128. * @param {Function} func Function to partialization.
  129. * @param {Array} params Function arguments to cache.
  130. * @returns {Function}
  131. */
  132. export function partial(func) {
  133. for (var _len2 = arguments.length, params = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
  134. params[_key2 - 1] = arguments[_key2];
  135. }
  136. return function _partial() {
  137. for (var _len3 = arguments.length, restParams = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
  138. restParams[_key3] = arguments[_key3];
  139. }
  140. return func.apply(this, params.concat(restParams));
  141. };
  142. }
  143. /**
  144. * Creates the functions that returns the function with cached arguments. If count if passed arguments will be matched
  145. * to the arguments defined in `func` then function will be invoked.
  146. * Arguments are added to the stack in direction from the left to the right.
  147. *
  148. * @example
  149. * ```
  150. * var replace = curry(function(find, replace, string) {
  151. * return string.replace(find, replace);
  152. * });
  153. *
  154. * // returns function with bounded first argument
  155. * var replace = replace('foo')
  156. *
  157. * // returns replaced string - all arguments was passed so function was invoked
  158. * replace('bar', 'Some test with foo...');
  159. *
  160. * ```
  161. *
  162. * @param {Function} func Function to currying.
  163. * @returns {Function}
  164. */
  165. export function curry(func) {
  166. var argsLength = func.length;
  167. function given(argsSoFar) {
  168. return function _curry() {
  169. for (var _len4 = arguments.length, params = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
  170. params[_key4] = arguments[_key4];
  171. }
  172. var passedArgsSoFar = argsSoFar.concat(params);
  173. var result = void 0;
  174. if (passedArgsSoFar.length >= argsLength) {
  175. result = func.apply(this, passedArgsSoFar);
  176. } else {
  177. result = given(passedArgsSoFar);
  178. }
  179. return result;
  180. };
  181. }
  182. return given([]);
  183. }
  184. /**
  185. * Creates the functions that returns the function with cached arguments. If count if passed arguments will be matched
  186. * to the arguments defined in `func` then function will be invoked.
  187. * Arguments are added to the stack in direction from the right to the left.
  188. *
  189. * @example
  190. * ```
  191. * var replace = curry(function(find, replace, string) {
  192. * return string.replace(find, replace);
  193. * });
  194. *
  195. * // returns function with bounded first argument
  196. * var replace = replace('Some test with foo...')
  197. *
  198. * // returns replaced string - all arguments was passed so function was invoked
  199. * replace('bar', 'foo');
  200. *
  201. * ```
  202. *
  203. * @param {Function} func Function to currying.
  204. * @returns {Function}
  205. */
  206. export function curryRight(func) {
  207. var argsLength = func.length;
  208. function given(argsSoFar) {
  209. return function _curry() {
  210. for (var _len5 = arguments.length, params = Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
  211. params[_key5] = arguments[_key5];
  212. }
  213. var passedArgsSoFar = argsSoFar.concat(params.reverse());
  214. var result = void 0;
  215. if (passedArgsSoFar.length >= argsLength) {
  216. result = func.apply(this, passedArgsSoFar);
  217. } else {
  218. result = given(passedArgsSoFar);
  219. }
  220. return result;
  221. };
  222. }
  223. return given([]);
  224. }