diff --git a/lodash.js b/lodash.js index 539c95355..0a560b5d2 100644 --- a/lodash.js +++ b/lodash.js @@ -1494,6 +1494,7 @@ nativeKeys = overArg(Object.keys, Object), nativeMax = Math.max, nativeMin = Math.min, + nativeNow = Date.now, nativeParseInt = context.parseInt, nativeRandom = Math.random, nativeReverse = arrayProto.reverse; @@ -3873,7 +3874,7 @@ } /** - * The base implementation of `setData` without support for hot loop detection. + * The base implementation of `setData` without support for hot loop shorting. * * @private * @param {Function} func The function to associate metadata with. @@ -3885,6 +3886,23 @@ return func; }; + /** + * The base implementation of `setToString` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var baseSetToString = !nativeDefineProperty ? identity : function(func, string) { + return nativeDefineProperty(func, 'toString', { + 'configurable': true, + 'enumerable': false, + 'value': constant(string), + 'writable': true + }); + }; + /** * The base implementation of `_.slice` without an iteratee call guard. * @@ -6368,25 +6386,7 @@ * @param {*} data The metadata. * @returns {Function} Returns `func`. */ - var setData = (function() { - var count = 0, - lastCalled = 0; - - return function(key, value) { - var stamp = now(), - remaining = HOT_SPAN - (stamp - lastCalled); - - lastCalled = stamp; - if (remaining > 0) { - if (++count >= HOT_COUNT) { - return key; - } - } else { - count = 0; - } - return baseSetData(key, value); - }; - }()); + var setData = shortOut(baseSetData); /** * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout). @@ -6408,14 +6408,7 @@ * @param {Function} string The `toString` result. * @returns {Function} Returns `func`. */ - var setToString = !nativeDefineProperty ? identity : function(func, string) { - return nativeDefineProperty(func, 'toString', { - 'configurable': true, - 'enumerable': false, - 'value': constant(string), - 'writable': true - }); - }; + var setToString = shortOut(baseSetToString); /** * Sets the `toString` method of `wrapper` to mimic the source of `reference` @@ -6432,6 +6425,35 @@ return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask))); } + /** + * Creates a function that'll short out and invoke `identity` instead + * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN` + * milliseconds. + * + * @private + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new shortable function. + */ + function shortOut(func) { + var count = 0, + lastCalled = 0; + + return function() { + var stamp = nativeNow(), + remaining = HOT_SPAN - (stamp - lastCalled); + + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return arguments[0]; + } + } else { + count = 0; + } + return func.apply(undefined, arguments); + }; + } + /** * Converts `string` to a property path array. *