mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-08 02:17:48 +00:00
Fix perf regressions in _.bind, _.groupBy, _.countBy, _.indexBy, and _.reduceRight.
Former-commit-id: 0972dd65af64b7cd1d7f2800a8a59c28183b8aba
This commit is contained in:
130
dist/lodash.js
vendored
130
dist/lodash.js
vendored
@@ -1127,10 +1127,20 @@
|
||||
return function(collection, callback, thisArg) {
|
||||
var result = {};
|
||||
callback = lodash.createCallback(callback, thisArg, 3);
|
||||
forEach(collection, function(value, key, collection) {
|
||||
key = String(callback(value, key, collection));
|
||||
setter(result, value, key, collection);
|
||||
});
|
||||
|
||||
var index = -1,
|
||||
length = collection ? collection.length : 0;
|
||||
|
||||
if (typeof length == 'number') {
|
||||
while (++index < length) {
|
||||
var value = collection[index];
|
||||
setter(result, value, callback(value, index, collection), collection);
|
||||
}
|
||||
} else {
|
||||
forOwn(collection, function(value, key, collection) {
|
||||
setter(result, value, callback(value, key, collection), collection);
|
||||
});
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
@@ -1163,11 +1173,20 @@
|
||||
isCurry = bitmask & 4,
|
||||
isCurryBound = bitmask & 8,
|
||||
isPartial = bitmask & 16,
|
||||
isPartialRight = bitmask & 32;
|
||||
isPartialRight = bitmask & 32,
|
||||
key = func;
|
||||
|
||||
if (!isBindKey && !isFunction(func)) {
|
||||
throw new TypeError;
|
||||
}
|
||||
if (isPartial && !partialArgs.length) {
|
||||
bitmask &= ~16;
|
||||
isPartial = partialArgs = false;
|
||||
}
|
||||
if (isPartialRight && !partialRightArgs.length) {
|
||||
bitmask &= ~32;
|
||||
isPartialRight = partialRightArgs = false;
|
||||
}
|
||||
var bindData = func && func.__bindData__;
|
||||
if (bindData) {
|
||||
if (isBind && !(bindData[1] & 1)) {
|
||||
@@ -1191,10 +1210,14 @@
|
||||
// use `Function#bind` if it exists and is fast
|
||||
// (in V8 `Function#bind` is slower except when partially applied)
|
||||
if (isBind && !(isBindKey || isCurry || isPartialRight) &&
|
||||
(support.fastBind || (nativeBind && partialArgs.length))) {
|
||||
var args = [func, thisArg];
|
||||
push.apply(args, partialArgs);
|
||||
var bound = nativeBind.call.apply(nativeBind, args);
|
||||
(support.fastBind || (nativeBind && isPartial))) {
|
||||
if (isPartial) {
|
||||
var args = [thisArg];
|
||||
push.apply(args, partialArgs);
|
||||
}
|
||||
var bound = isPartial
|
||||
? nativeBind.apply(func, args)
|
||||
: nativeBind.call(func, thisArg);
|
||||
}
|
||||
else {
|
||||
bound = function() {
|
||||
@@ -1203,14 +1226,14 @@
|
||||
var args = arguments,
|
||||
thisBinding = isBind ? thisArg : this;
|
||||
|
||||
if (partialArgs) {
|
||||
if (isPartial) {
|
||||
unshift.apply(args, partialArgs);
|
||||
}
|
||||
if (partialRightArgs) {
|
||||
if (isPartialRight) {
|
||||
push.apply(args, partialRightArgs);
|
||||
}
|
||||
if (isCurry && args.length < arity) {
|
||||
bitmask |= 16 & ~32
|
||||
bitmask |= 16 & ~32;
|
||||
return createBound(func, (isCurryBound ? bitmask : bitmask & ~3), args, null, thisArg, arity);
|
||||
}
|
||||
if (isBindKey) {
|
||||
@@ -1228,13 +1251,7 @@
|
||||
return func.apply(thisBinding, args);
|
||||
};
|
||||
}
|
||||
// take a snapshot of `arguments` before juggling
|
||||
bindData = nativeSlice.call(arguments);
|
||||
if (isBindKey) {
|
||||
var key = thisArg;
|
||||
thisArg = func;
|
||||
}
|
||||
setBindData(bound, bindData);
|
||||
setBindData(bound, nativeSlice.call(arguments));
|
||||
return bound;
|
||||
}
|
||||
|
||||
@@ -2970,18 +2987,22 @@
|
||||
* // => logs each number from right to left and returns '3,2,1'
|
||||
*/
|
||||
function forEachRight(collection, callback, thisArg) {
|
||||
var iterable = collection,
|
||||
length = collection ? collection.length : 0;
|
||||
|
||||
if (typeof length != 'number') {
|
||||
var length = collection ? collection.length : 0;
|
||||
callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
|
||||
if (typeof length == 'number') {
|
||||
while (length--) {
|
||||
if (callback(collection[length], length, collection) === false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var props = keys(collection);
|
||||
length = props.length;
|
||||
forOwn(collection, function(value, key, collection) {
|
||||
key = props ? props[--length] : --length;
|
||||
return callback(collection[key], key, collection);
|
||||
});
|
||||
}
|
||||
callback = baseCreateCallback(callback, thisArg, 3);
|
||||
forEach(collection, function(value, index, collection) {
|
||||
index = props ? props[--length] : --length;
|
||||
return callback(iterable[index], index, collection);
|
||||
});
|
||||
return collection;
|
||||
}
|
||||
|
||||
@@ -4014,7 +4035,7 @@
|
||||
var index = sortedIndex(array, value);
|
||||
return array[index] === value ? index : -1;
|
||||
}
|
||||
return array ? baseIndexOf(array, value, fromIndex) : -1;
|
||||
return baseIndexOf(array, value, fromIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4780,7 +4801,7 @@
|
||||
|
||||
while (++index < length) {
|
||||
var key = funcs[index];
|
||||
object[key] = bind(object[key], object);
|
||||
object[key] = createBound(object[key], 1, null, null, object);
|
||||
}
|
||||
return object;
|
||||
}
|
||||
@@ -4820,7 +4841,7 @@
|
||||
* // => 'hi, moe!'
|
||||
*/
|
||||
function bindKey(object, key) {
|
||||
return createBound(object, 19, nativeSlice.call(arguments, 2), null, key);
|
||||
return createBound(key, 19, nativeSlice.call(arguments, 2), null, object);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5016,6 +5037,7 @@
|
||||
function debounce(func, wait, options) {
|
||||
var args,
|
||||
result,
|
||||
stamp,
|
||||
thisArg,
|
||||
callCount = 0,
|
||||
lastCalled = 0,
|
||||
@@ -5036,24 +5058,30 @@
|
||||
maxWait = 'maxWait' in options && nativeMax(wait, options.maxWait || 0);
|
||||
trailing = 'trailing' in options ? options.trailing : trailing;
|
||||
}
|
||||
var clear = function() {
|
||||
clearTimeout(maxTimeoutId);
|
||||
clearTimeout(timeoutId);
|
||||
callCount = 0;
|
||||
maxTimeoutId = timeoutId = null;
|
||||
};
|
||||
|
||||
var delayed = function() {
|
||||
var isCalled = trailing && (!leading || callCount > 1);
|
||||
clear();
|
||||
if (isCalled) {
|
||||
lastCalled = now();
|
||||
result = func.apply(thisArg, args);
|
||||
var remaining = wait - (now() - stamp);
|
||||
if (remaining <= 0) {
|
||||
var isCalled = trailing && (!leading || callCount > 1);
|
||||
if (maxTimeoutId) {
|
||||
clearTimeout(maxTimeoutId);
|
||||
}
|
||||
callCount = 0;
|
||||
maxTimeoutId = timeoutId = null;
|
||||
if (isCalled) {
|
||||
lastCalled = now();
|
||||
result = func.apply(thisArg, args);
|
||||
}
|
||||
} else {
|
||||
timeoutId = setTimeout(delayed, remaining);
|
||||
}
|
||||
};
|
||||
|
||||
var maxDelayed = function() {
|
||||
clear();
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
callCount = 0;
|
||||
maxTimeoutId = timeoutId = null;
|
||||
if (trailing || (maxWait !== wait)) {
|
||||
lastCalled = now();
|
||||
result = func.apply(thisArg, args);
|
||||
@@ -5062,26 +5090,24 @@
|
||||
|
||||
return function() {
|
||||
args = arguments;
|
||||
stamp = now();
|
||||
thisArg = this;
|
||||
callCount++;
|
||||
|
||||
// avoid issues with Titanium and `undefined` timeout ids
|
||||
// https://github.com/appcelerator/titanium_mobile/blob/3_1_0_GA/android/titanium/src/java/ti/modules/titanium/TitaniumModule.java#L185-L192
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
if (maxWait === false) {
|
||||
if (leading && callCount < 2) {
|
||||
result = func.apply(thisArg, args);
|
||||
}
|
||||
} else {
|
||||
var stamp = now();
|
||||
if (!maxTimeoutId && !leading) {
|
||||
lastCalled = stamp;
|
||||
}
|
||||
var remaining = maxWait - (stamp - lastCalled);
|
||||
if (remaining <= 0) {
|
||||
clearTimeout(maxTimeoutId);
|
||||
maxTimeoutId = null;
|
||||
if (maxTimeoutId) {
|
||||
clearTimeout(maxTimeoutId);
|
||||
maxTimeoutId = null;
|
||||
}
|
||||
lastCalled = stamp;
|
||||
result = func.apply(thisArg, args);
|
||||
}
|
||||
@@ -5089,7 +5115,7 @@
|
||||
maxTimeoutId = setTimeout(maxDelayed, remaining);
|
||||
}
|
||||
}
|
||||
if (wait !== maxWait) {
|
||||
if (!timeoutId && wait !== maxWait) {
|
||||
timeoutId = setTimeout(delayed, wait);
|
||||
}
|
||||
return result;
|
||||
|
||||
Reference in New Issue
Block a user