mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-10 02:47:50 +00:00
Reorganize wrappers, adding SetCache as a hybrid cache combining ES6 Set and object lookups,
This commit is contained in:
542
lodash.js
542
lodash.js
@@ -541,19 +541,6 @@
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* An implementation of `_.contains` for cache objects that mimics the return
|
|
||||||
* signature of `_.indexOf` by returning `0` if the value is found, else `-1`.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {Object} cache The cache object to inspect.
|
|
||||||
* @param {*} value The value to search for.
|
|
||||||
* @returns {number} Returns `0` if `value` is found, else `-1`.
|
|
||||||
*/
|
|
||||||
function cacheIndexOf(cache, value) {
|
|
||||||
return cache.has(value) ? 0 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used by `_.max` and `_.min` as the default callback for string values.
|
* Used by `_.max` and `_.min` as the default callback for string values.
|
||||||
*
|
*
|
||||||
@@ -637,7 +624,7 @@
|
|||||||
// for `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
|
// for `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
|
||||||
//
|
//
|
||||||
// This also ensures a stable sort in V8 and other engines.
|
// This also ensures a stable sort in V8 and other engines.
|
||||||
// See https://code.google.com/p/v8/issues/detail?id=90
|
// See https://code.google.com/p/v8/issues/detail?id=90.
|
||||||
return object.index - other.index;
|
return object.index - other.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1082,6 +1069,20 @@
|
|||||||
return new LodashWrapper(value);
|
return new LodashWrapper(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base constructor for creating `lodash` wrapper objects.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {*} value The value to wrap.
|
||||||
|
* @param {boolean} [chainAll=false] Enable chaining for all wrapper methods.
|
||||||
|
* @param {Array} [queue=[]] Actions to peform to resolve the unwrapped value.
|
||||||
|
*/
|
||||||
|
function LodashWrapper(value, chainAll, queue) {
|
||||||
|
this.__chain__ = !!chainAll;
|
||||||
|
this.__queue__ = queue || [];
|
||||||
|
this.__wrapped__ = value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object environment feature flags.
|
* An object environment feature flags.
|
||||||
*
|
*
|
||||||
@@ -1306,6 +1307,229 @@
|
|||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {*} value The value to wrap.
|
||||||
|
*/
|
||||||
|
function LazyWrapper(value) {
|
||||||
|
this.dir = 1;
|
||||||
|
this.dropCount = 0;
|
||||||
|
this.filtered = false;
|
||||||
|
this.iteratees = null;
|
||||||
|
this.takeCount = POSITIVE_INFINITY;
|
||||||
|
this.views = null;
|
||||||
|
this.wrapped = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a clone of the lazy wrapper object.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @name clone
|
||||||
|
* @memberOf LazyWrapper
|
||||||
|
* @returns {Object} Returns the cloned `LazyWrapper` object.
|
||||||
|
*/
|
||||||
|
function lazyClone() {
|
||||||
|
var iteratees = this.iteratees,
|
||||||
|
views = this.views,
|
||||||
|
result = new LazyWrapper(this.wrapped);
|
||||||
|
|
||||||
|
result.dir = this.dir;
|
||||||
|
result.dropCount = this.dropCount;
|
||||||
|
result.filtered = this.filtered;
|
||||||
|
result.iteratees = iteratees ? baseSlice(iteratees) : null;
|
||||||
|
result.takeCount = this.takeCount;
|
||||||
|
result.views = views ? baseSlice(views) : null;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverses the direction of lazy iteration.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @name reverse
|
||||||
|
* @memberOf LazyWrapper
|
||||||
|
* @returns {Object} Returns the new reversed `LazyWrapper` object.
|
||||||
|
*/
|
||||||
|
function lazyReverse() {
|
||||||
|
var filtered = this.filtered,
|
||||||
|
result = filtered ? new LazyWrapper(this) : this.clone();
|
||||||
|
|
||||||
|
result.dir = this.dir * -1;
|
||||||
|
result.filtered = filtered;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the unwrapped value from its lazy wrapper.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @name value
|
||||||
|
* @memberOf LazyWrapper
|
||||||
|
* @returns {*} Returns the unwrapped value.
|
||||||
|
*/
|
||||||
|
function lazyValue() {
|
||||||
|
var array = this.wrapped.value(),
|
||||||
|
dir = this.dir,
|
||||||
|
isRight = dir < 0,
|
||||||
|
length = array.length,
|
||||||
|
view = getView(0, length, this.views),
|
||||||
|
start = view.start,
|
||||||
|
end = view.end,
|
||||||
|
dropCount = this.dropCount,
|
||||||
|
takeCount = nativeMin(end - start, this.takeCount - dropCount),
|
||||||
|
index = isRight ? end : start - 1,
|
||||||
|
iteratees = this.iteratees,
|
||||||
|
iterLength = iteratees ? iteratees.length : 0,
|
||||||
|
resIndex = 0,
|
||||||
|
result = [];
|
||||||
|
|
||||||
|
outer:
|
||||||
|
while (length-- && resIndex < takeCount) {
|
||||||
|
index += dir;
|
||||||
|
|
||||||
|
var iterIndex = -1,
|
||||||
|
value = array[index];
|
||||||
|
|
||||||
|
while (++iterIndex < iterLength) {
|
||||||
|
var data = iteratees[iterIndex],
|
||||||
|
iteratee = data.iteratee,
|
||||||
|
computed = iteratee(value, index, array),
|
||||||
|
type = data.type;
|
||||||
|
|
||||||
|
if (type == LAZY_MAP_FLAG) {
|
||||||
|
value = computed;
|
||||||
|
} else if (!computed) {
|
||||||
|
if (type == LAZY_FILTER_FLAG) {
|
||||||
|
continue outer;
|
||||||
|
} else {
|
||||||
|
break outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dropCount) {
|
||||||
|
dropCount--;
|
||||||
|
} else {
|
||||||
|
result[resIndex++] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isRight ? result.reverse() : result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a cache object for use by `_.memoize`.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @static
|
||||||
|
* @name Cache
|
||||||
|
* @memberOf _.memoize
|
||||||
|
*/
|
||||||
|
function MemCache() {
|
||||||
|
this.__data__ = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value at `key`.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @name get
|
||||||
|
* @memberOf _.memoize.Cache
|
||||||
|
* @param {string} key The key of the value to retrieve.
|
||||||
|
* @returns {*} Returns the cached value.
|
||||||
|
*/
|
||||||
|
function memGet(key) {
|
||||||
|
return this.__data__[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a value for `key` exists.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @name has
|
||||||
|
* @memberOf _.memoize.Cache
|
||||||
|
* @param {string} key The name of the entry to check.
|
||||||
|
* @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
|
||||||
|
*/
|
||||||
|
function memHas(key) {
|
||||||
|
return key != '__proto__' && hasOwnProperty.call(this.__data__, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds `value` to the cache at `key`.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @name set
|
||||||
|
* @memberOf _.memoize.Cache
|
||||||
|
* @param {string} key The key of the value to set.
|
||||||
|
* @param {*} value The value to set.
|
||||||
|
* @returns {Object} Returns the cache object.
|
||||||
|
*/
|
||||||
|
function memSet(key, value) {
|
||||||
|
if (key != '__proto__') {
|
||||||
|
this.__data__[key] = value;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a cache object to optimize linear searches of large arrays.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Array} [values] The values to cache.
|
||||||
|
*/
|
||||||
|
function SetCache(values) {
|
||||||
|
var length = values ? values.length : 0;
|
||||||
|
|
||||||
|
this.data = { 'number': {}, 'set': new Set };
|
||||||
|
while (length--) {
|
||||||
|
this.push(values[length]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if `value` is in `cache` mimicking the return signature of
|
||||||
|
* `_.indexOf` by returning `0` if the value is found, else `-1`.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Object} cache The cache object to search.
|
||||||
|
* @param {*} value The value to search for.
|
||||||
|
* @returns {number} Returns `0` if `value` is found, else `-1`.
|
||||||
|
*/
|
||||||
|
function cacheIndexOf(cache, value) {
|
||||||
|
var type = typeof value,
|
||||||
|
data = cache.data,
|
||||||
|
result = type == 'number' ? data[type][value] : data.set.has(value);
|
||||||
|
|
||||||
|
return result ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds `value` to the cache.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @name push
|
||||||
|
* @memberOf SetCache
|
||||||
|
* @param {*} value The value to add.
|
||||||
|
*/
|
||||||
|
function cachePush(value) {
|
||||||
|
var data = this.data,
|
||||||
|
type = typeof value;
|
||||||
|
|
||||||
|
if (type == 'number') {
|
||||||
|
data[type][value] = true;
|
||||||
|
} else {
|
||||||
|
data.set.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A specialized version of `_.max` for arrays without support for iteratees.
|
* A specialized version of `_.max` for arrays without support for iteratees.
|
||||||
*
|
*
|
||||||
@@ -1379,18 +1603,6 @@
|
|||||||
: objectValue;
|
: objectValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Used by `_.matches` to clone `source` values, letting uncloneable values
|
|
||||||
* passthu instead of returning empty objects.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {*} value The value to clone.
|
|
||||||
* @returns {*} Returns the cloned value.
|
|
||||||
*/
|
|
||||||
function clonePassthru(value) {
|
|
||||||
return isCloneable(value) ? undefined : value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base implementation of `_.assign` without support for argument juggling,
|
* The base implementation of `_.assign` without support for argument juggling,
|
||||||
* multiple sources, and `this` binding.
|
* multiple sources, and `this` binding.
|
||||||
@@ -1630,15 +1842,16 @@
|
|||||||
}
|
}
|
||||||
var index = -1,
|
var index = -1,
|
||||||
indexOf = getIndexOf(),
|
indexOf = getIndexOf(),
|
||||||
prereq = indexOf == baseIndexOf,
|
isCommon = indexOf == baseIndexOf,
|
||||||
isLarge = prereq && createCache && values && values.length >= 200,
|
isLarge = isCommon && values && values.length >= 200,
|
||||||
isCommon = prereq && !isLarge,
|
cache = isLarge && createCache(values),
|
||||||
result = [],
|
result = [],
|
||||||
valuesLength = values.length;
|
valuesLength = values.length;
|
||||||
|
|
||||||
if (isLarge) {
|
if (cache) {
|
||||||
indexOf = cacheIndexOf;
|
indexOf = cacheIndexOf;
|
||||||
values = createCache(values);
|
isCommon = false;
|
||||||
|
values = cache;
|
||||||
}
|
}
|
||||||
outer:
|
outer:
|
||||||
while (++index < length) {
|
while (++index < length) {
|
||||||
@@ -2381,14 +2594,14 @@
|
|||||||
var index = -1,
|
var index = -1,
|
||||||
indexOf = getIndexOf(),
|
indexOf = getIndexOf(),
|
||||||
length = array.length,
|
length = array.length,
|
||||||
prereq = indexOf == baseIndexOf,
|
isCommon = indexOf == baseIndexOf,
|
||||||
isLarge = prereq && createCache && length >= 200,
|
isLarge = isCommon && length >= 200,
|
||||||
isCommon = prereq && !isLarge,
|
seen = isLarge && createCache(),
|
||||||
result = [];
|
result = [];
|
||||||
|
|
||||||
if (isLarge) {
|
if (seen) {
|
||||||
var seen = createCache();
|
|
||||||
indexOf = cacheIndexOf;
|
indexOf = cacheIndexOf;
|
||||||
|
isCommon = false;
|
||||||
} else {
|
} else {
|
||||||
seen = iteratee ? [] : result;
|
seen = iteratee ? [] : result;
|
||||||
}
|
}
|
||||||
@@ -2471,6 +2684,18 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by `_.matches` to clone `source` values, letting uncloneable values
|
||||||
|
* passthu instead of returning empty objects.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {*} value The value to clone.
|
||||||
|
* @returns {*} Returns the cloned value.
|
||||||
|
*/
|
||||||
|
function clonePassthru(value) {
|
||||||
|
return isCloneable(value) ? undefined : value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an array that is the composition of partially applied arguments,
|
* Creates an array that is the composition of partially applied arguments,
|
||||||
* placeholders, and provided arguments into a single array of arguments.
|
* placeholders, and provided arguments into a single array of arguments.
|
||||||
@@ -2619,21 +2844,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a cache object to optimize linear searches of large arrays.
|
* Creates a cache object if supported.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {Array} [array=[]] The array to search.
|
* @param {Array} [values] The values to cache.
|
||||||
* @returns {Object} Returns the new cache object.
|
* @returns {Object} Returns the new cache object.
|
||||||
*/
|
*/
|
||||||
var createCache = Set && function(array) {
|
var createCache = !Set ? noop : function(values) {
|
||||||
var cache = new Set,
|
return new SetCache(values);
|
||||||
length = array ? array.length : 0;
|
|
||||||
|
|
||||||
cache.push = cache.add;
|
|
||||||
while (length--) {
|
|
||||||
cache.push(array[length]);
|
|
||||||
}
|
|
||||||
return cache;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -3116,7 +3334,7 @@
|
|||||||
var length = object.length,
|
var length = object.length,
|
||||||
prereq = isLength(length) && isIndex(index, length);
|
prereq = isLength(length) && isIndex(index, length);
|
||||||
} else {
|
} else {
|
||||||
prereq = type == 'string';
|
prereq = type == 'string';
|
||||||
}
|
}
|
||||||
return prereq && object[index] === value;
|
return prereq && object[index] === value;
|
||||||
}
|
}
|
||||||
@@ -3845,8 +4063,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an array of unique values present in all provided arrays using
|
* Creates an array of unique values in all provided arrays using `SameValueZero`
|
||||||
* `SameValueZero` for equality comparisons.
|
* for equality comparisons.
|
||||||
*
|
*
|
||||||
* **Note:** `SameValueZero` comparisons are like strict equality comparisons,
|
* **Note:** `SameValueZero` comparisons are like strict equality comparisons,
|
||||||
* e.g. `===`, except that `NaN` matches `NaN`. See the
|
* e.g. `===`, except that `NaN` matches `NaN`. See the
|
||||||
@@ -3869,14 +4087,13 @@
|
|||||||
argsLength = arguments.length,
|
argsLength = arguments.length,
|
||||||
caches = [],
|
caches = [],
|
||||||
indexOf = getIndexOf(),
|
indexOf = getIndexOf(),
|
||||||
prereq = createCache && indexOf == baseIndexOf;
|
isCommon = indexOf == baseIndexOf;
|
||||||
|
|
||||||
while (++argsIndex < argsLength) {
|
while (++argsIndex < argsLength) {
|
||||||
var value = arguments[argsIndex];
|
var value = arguments[argsIndex];
|
||||||
if (isArray(value) || isArguments(value)) {
|
if (isArray(value) || isArguments(value)) {
|
||||||
args.push(value);
|
args.push(value);
|
||||||
caches.push(prereq && value.length >= 120 &&
|
caches.push(isCommon && value.length >= 120 && createCache(argsIndex && value));
|
||||||
createCache(argsIndex && value));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
argsLength = args.length;
|
argsLength = args.length;
|
||||||
@@ -4640,7 +4857,7 @@
|
|||||||
* @memberOf _
|
* @memberOf _
|
||||||
* @category Chain
|
* @category Chain
|
||||||
* @param {*} value The value to wrap.
|
* @param {*} value The value to wrap.
|
||||||
* @returns {Object} Returns the new `LodashWrapper` object.
|
* @returns {Object} Returns the new `lodash` object.
|
||||||
* @example
|
* @example
|
||||||
*
|
*
|
||||||
* var users = [
|
* var users = [
|
||||||
@@ -4710,30 +4927,13 @@
|
|||||||
return interceptor.call(thisArg, value);
|
return interceptor.call(thisArg, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A fast path for creating `lodash` wrapper objects.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {*} value The value to wrap.
|
|
||||||
* @param {boolean} [chainAll=false] Enable chaining for all methods.
|
|
||||||
* @param {Array} [queue=[]] Actions to peform to resolve the unwrapped value.
|
|
||||||
* @returns {Object} Returns a `LodashWrapper` instance.
|
|
||||||
*/
|
|
||||||
function LodashWrapper(value, chainAll, queue) {
|
|
||||||
this.__chain__ = !!chainAll;
|
|
||||||
this.__queue__ = queue || [];
|
|
||||||
this.__wrapped__ = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables explicit method chaining on the wrapper object.
|
* Enables explicit method chaining on the wrapper object.
|
||||||
*
|
*
|
||||||
* @name chain
|
* @name chain
|
||||||
* @memberOf _
|
* @memberOf _
|
||||||
* @category Chain
|
* @category Chain
|
||||||
* @returns {*} Returns the `LodashWrapper` object.
|
* @returns {*} Returns the `lodash` object.
|
||||||
* @example
|
* @example
|
||||||
*
|
*
|
||||||
* var users = [
|
* var users = [
|
||||||
@@ -4765,7 +4965,7 @@
|
|||||||
* @name chain
|
* @name chain
|
||||||
* @memberOf _
|
* @memberOf _
|
||||||
* @category Chain
|
* @category Chain
|
||||||
* @returns {Object} Returns the new reversed `LodashWrapper` object.
|
* @returns {Object} Returns the new reversed `lodash` object.
|
||||||
* @example
|
* @example
|
||||||
*
|
*
|
||||||
* var array = [1, 2, 3];
|
* var array = [1, 2, 3];
|
||||||
@@ -4833,120 +5033,6 @@
|
|||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps `value` as a `LazyWrapper` object.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {*} value The value to wrap.
|
|
||||||
* @returns {Object} Returns a `LazyWrapper` instance.
|
|
||||||
*/
|
|
||||||
function LazyWrapper(value) {
|
|
||||||
this.dir = 1;
|
|
||||||
this.dropCount = 0;
|
|
||||||
this.filtered = false;
|
|
||||||
this.iteratees = null;
|
|
||||||
this.takeCount = POSITIVE_INFINITY;
|
|
||||||
this.views = null;
|
|
||||||
this.wrapped = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a clone of the `LazyWrapper` object.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @name clone
|
|
||||||
* @memberOf LazyWrapper
|
|
||||||
* @returns {Object} Returns the cloned `LazyWrapper` object.
|
|
||||||
*/
|
|
||||||
function lazyClone() {
|
|
||||||
var iteratees = this.iteratees,
|
|
||||||
views = this.views,
|
|
||||||
result = new LazyWrapper(this.wrapped);
|
|
||||||
|
|
||||||
result.dir = this.dir;
|
|
||||||
result.dropCount = this.dropCount;
|
|
||||||
result.filtered = this.filtered;
|
|
||||||
result.iteratees = iteratees ? baseSlice(iteratees) : null;
|
|
||||||
result.takeCount = this.takeCount;
|
|
||||||
result.views = views ? baseSlice(views) : null;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverses the direction of lazy iteration.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @name reverse
|
|
||||||
* @memberOf LazyWrapper
|
|
||||||
* @returns {Object} Returns the new reversed `LazyWrapper` object.
|
|
||||||
*/
|
|
||||||
function lazyReverse() {
|
|
||||||
var filtered = this.filtered,
|
|
||||||
result = filtered ? new LazyWrapper(this) : this.clone();
|
|
||||||
|
|
||||||
result.dir = this.dir * -1;
|
|
||||||
result.filtered = filtered;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracts the unwrapped value from its wrapper.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @name value
|
|
||||||
* @memberOf LazyWrapper
|
|
||||||
* @returns {*} Returns the unwrapped value.
|
|
||||||
*/
|
|
||||||
function lazyValue() {
|
|
||||||
var array = this.wrapped.value(),
|
|
||||||
dir = this.dir,
|
|
||||||
isRight = dir < 0,
|
|
||||||
length = array.length,
|
|
||||||
view = getView(0, length, this.views),
|
|
||||||
start = view.start,
|
|
||||||
end = view.end,
|
|
||||||
dropCount = this.dropCount,
|
|
||||||
takeCount = nativeMin(end - start, this.takeCount - dropCount),
|
|
||||||
index = isRight ? end : start - 1,
|
|
||||||
iteratees = this.iteratees,
|
|
||||||
iterLength = iteratees ? iteratees.length : 0,
|
|
||||||
resIndex = 0,
|
|
||||||
result = [];
|
|
||||||
|
|
||||||
outer:
|
|
||||||
while (length-- && resIndex < takeCount) {
|
|
||||||
index += dir;
|
|
||||||
|
|
||||||
var iterIndex = -1,
|
|
||||||
value = array[index];
|
|
||||||
|
|
||||||
while (++iterIndex < iterLength) {
|
|
||||||
var data = iteratees[iterIndex],
|
|
||||||
iteratee = data.iteratee,
|
|
||||||
computed = iteratee(value, index, array),
|
|
||||||
type = data.type;
|
|
||||||
|
|
||||||
if (type == LAZY_MAP_FLAG) {
|
|
||||||
value = computed;
|
|
||||||
} else if (!computed) {
|
|
||||||
if (type == LAZY_FILTER_FLAG) {
|
|
||||||
continue outer;
|
|
||||||
} else {
|
|
||||||
break outer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (dropCount) {
|
|
||||||
dropCount--;
|
|
||||||
} else {
|
|
||||||
result[resIndex++] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return isRight ? result.reverse() : result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an array of elements corresponding to the specified keys, or indexes,
|
* Creates an array of elements corresponding to the specified keys, or indexes,
|
||||||
* of the collection. Keys may be specified as individual arguments or as arrays
|
* of the collection. Keys may be specified as individual arguments or as arrays
|
||||||
@@ -4975,9 +5061,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if `value` is present in `collection` using `SameValueZero` for
|
* Checks if `value` is in `collection` using `SameValueZero` for equality
|
||||||
* equality comparisons. If `fromIndex` is negative, it is used as the offset
|
* comparisons. If `fromIndex` is negative, it is used as the offset from
|
||||||
* from the end of the collection.
|
* the end of the collection.
|
||||||
*
|
*
|
||||||
* **Note:** `SameValueZero` comparisons are like strict equality comparisons,
|
* **Note:** `SameValueZero` comparisons are like strict equality comparisons,
|
||||||
* e.g. `===`, except that `NaN` matches `NaN`. See the
|
* e.g. `===`, except that `NaN` matches `NaN`. See the
|
||||||
@@ -4989,7 +5075,7 @@
|
|||||||
* @alias include
|
* @alias include
|
||||||
* @category Collection
|
* @category Collection
|
||||||
* @param {Array|Object|string} collection The collection to search.
|
* @param {Array|Object|string} collection The collection to search.
|
||||||
* @param {*} target The value to check for.
|
* @param {*} target The value to search for.
|
||||||
* @param {number} [fromIndex=0] The index to search from.
|
* @param {number} [fromIndex=0] The index to search from.
|
||||||
* @returns {boolean} Returns `true` if a matching element is found, else `false`.
|
* @returns {boolean} Returns `true` if a matching element is found, else `false`.
|
||||||
* @example
|
* @example
|
||||||
@@ -6944,63 +7030,6 @@
|
|||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the cache used by `_.memoize`.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @static
|
|
||||||
* @name Cache
|
|
||||||
* @memberOf _.memoize
|
|
||||||
*/
|
|
||||||
function MemCache() {
|
|
||||||
this.__wrapped__ = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value associated with `key`.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @name get
|
|
||||||
* @memberOf _.memoize.Cache
|
|
||||||
* @param {string} key The key of the value to retrieve.
|
|
||||||
* @returns {*} Returns the cached value.
|
|
||||||
*/
|
|
||||||
function memGet(key) {
|
|
||||||
return this.__wrapped__[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if an entry for `key` exists.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @name get
|
|
||||||
* @memberOf _.memoize.Cache
|
|
||||||
* @param {string} key The name of the entry to check.
|
|
||||||
* @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
|
|
||||||
*/
|
|
||||||
function memHas(key) {
|
|
||||||
return key != '__proto__' && hasOwnProperty.call(this.__wrapped__, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the value associated with `key`.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @name get
|
|
||||||
* @memberOf _.memoize.Cache
|
|
||||||
* @param {string} key The key of the value to set.
|
|
||||||
* @param {*} value The value to set.
|
|
||||||
* @returns {Object} Returns the cache object.
|
|
||||||
*/
|
|
||||||
function memSet(key, value) {
|
|
||||||
if (key != '__proto__') {
|
|
||||||
this.__wrapped__[key] = value;
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a clone of `value`. If `isDeep` is `true` nested objects are cloned,
|
* Creates a clone of `value`. If `isDeep` is `true` nested objects are cloned,
|
||||||
* otherwise they are assigned by reference. If `customizer` is provided it is
|
* otherwise they are assigned by reference. If `customizer` is provided it is
|
||||||
@@ -7381,8 +7410,8 @@
|
|||||||
* // => false
|
* // => false
|
||||||
*/
|
*/
|
||||||
function isFunction(value) {
|
function isFunction(value) {
|
||||||
// use `|| false` to avoid a Chakra bug in compatibility modes of IE 11
|
// Use `|| false` to avoid a Chakra bug in compatibility modes of IE 11.
|
||||||
// https://github.com/jashkenas/underscore/issues/1621
|
// See https://github.com/jashkenas/underscore/issues/1621.
|
||||||
return typeof value == 'function' || false;
|
return typeof value == 'function' || false;
|
||||||
}
|
}
|
||||||
// fallback for environments that return incorrect `typeof` operator results
|
// fallback for environments that return incorrect `typeof` operator results
|
||||||
@@ -7419,8 +7448,8 @@
|
|||||||
* // => false
|
* // => false
|
||||||
*/
|
*/
|
||||||
function isObject(value) {
|
function isObject(value) {
|
||||||
// avoid a V8 bug in Chrome 19-20
|
// Avoid a V8 bug in Chrome 19-20.
|
||||||
// https://code.google.com/p/v8/issues/detail?id=2291
|
// See https://code.google.com/p/v8/issues/detail?id=2291.
|
||||||
var type = typeof value;
|
var type = typeof value;
|
||||||
return type == 'function' || (value && type == 'object') || false;
|
return type == 'function' || (value && type == 'object') || false;
|
||||||
}
|
}
|
||||||
@@ -9557,7 +9586,7 @@
|
|||||||
parseInt = function(value, radix, guard) {
|
parseInt = function(value, radix, guard) {
|
||||||
// Firefox < 21 and Opera < 15 follow ES3 for `parseInt` and
|
// Firefox < 21 and Opera < 15 follow ES3 for `parseInt` and
|
||||||
// Chrome fails to trim leading <BOM> whitespace characters.
|
// Chrome fails to trim leading <BOM> whitespace characters.
|
||||||
// See https://code.google.com/p/v8/issues/detail?id=3109
|
// See https://code.google.com/p/v8/issues/detail?id=3109.
|
||||||
value = trim(value);
|
value = trim(value);
|
||||||
radix = guard ? 0 : +radix;
|
radix = guard ? 0 : +radix;
|
||||||
return nativeParseInt(value, radix || (reHexPrefix.test(value) ? 16 : 10));
|
return nativeParseInt(value, radix || (reHexPrefix.test(value) ? 16 : 10));
|
||||||
@@ -9852,6 +9881,9 @@
|
|||||||
MemCache.prototype.has = memHas;
|
MemCache.prototype.has = memHas;
|
||||||
MemCache.prototype.set = memSet;
|
MemCache.prototype.set = memSet;
|
||||||
|
|
||||||
|
// add functions to the set cache
|
||||||
|
SetCache.prototype.push = cachePush;
|
||||||
|
|
||||||
// assign cache to `_.memoize`
|
// assign cache to `_.memoize`
|
||||||
memoize.Cache = MemCache;
|
memoize.Cache = MemCache;
|
||||||
|
|
||||||
@@ -10191,7 +10223,7 @@
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
// add `LazyWrapper` methods to `LodashWrapper`
|
// add `LazyWrapper` methods to `lodash.prototype`
|
||||||
baseForOwn(LazyWrapper.prototype, function(func, methodName) {
|
baseForOwn(LazyWrapper.prototype, function(func, methodName) {
|
||||||
var retUnwrapped = /^(?:first|last)$/.test(methodName);
|
var retUnwrapped = /^(?:first|last)$/.test(methodName);
|
||||||
|
|
||||||
@@ -10218,7 +10250,7 @@
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// add `Array.prototype` functions to `LodashWrapper`
|
// add `Array.prototype` functions to `lodash.prototype`
|
||||||
arrayEach(['concat', 'join', 'pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
|
arrayEach(['concat', 'join', 'pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
|
||||||
var arrayFunc = arrayProto[methodName],
|
var arrayFunc = arrayProto[methodName],
|
||||||
chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
|
chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
|
||||||
|
|||||||
Reference in New Issue
Block a user