Ensure _.reduce doesn't assign accumulator a collection value if its length is 0.

This commit is contained in:
John-David Dalton
2013-12-25 00:21:45 -06:00
parent 2dab4ccf85
commit 0438fa6816
5 changed files with 41 additions and 27 deletions

View File

@@ -4109,7 +4109,7 @@
var index = -1,
length = collection.length;
if (noaccum) {
if (noaccum && length) {
accumulator = collection[++index];
}
while (++index < length) {

View File

@@ -23,7 +23,7 @@ for(t=t&&typeof r=="undefined"?t:ut(t,r,3);++e<o&&(r=u[e],false!==t(n[r],r,n));)
}function Rt(n){return typeof n=="string"||n&&typeof n=="object"&&xr.call(n)==H||false}function Tt(n){for(var t=-1,r=Zr(n),e=r.length,u=ir(e);++t<e;)u[t]=n[r[t]];return u}function Pt(n,t,r){var e=n?n.length:0;if(r=typeof r=="number"?r:0,typeof e=="number"){if(r>=e)return false;if(typeof n=="string"||!Xr(n)&&Rt(n))return qr?qr.call(n,t,r):-1<n.indexOf(t,r);var u=dt();return r=(0>r?Kr(0,e+r):r)||0,-1<u(n,t,r)}var o=-1,a=false;return ft(n,function(n){return++o<r?void 0:!(a=n===t)}),a}function Dt(n,t,r){var e=true;
if(t=v.createCallback(t,r,3),Xr(n)){r=-1;for(var u=n.length;++r<u&&(e=!!t(n[r],r,n)););}else ft(n,function(n,r,u){return e=!!t(n,r,u)});return e}function $t(n,t,r){var e=[];if(t=v.createCallback(t,r,3),Xr(n)){r=-1;for(var u=n.length;++r<u;){var o=n[r];t(o,r,n)&&e.push(o)}}else ft(n,function(n,r,u){t(n,r,u)&&e.push(n)});return e}function qt(n,t,r){if(t=v.createCallback(t,r,3),!Xr(n)){var e;return ft(n,function(n,r,u){return t(n,r,u)?(e=n,false):void 0}),e}r=-1;for(var u=n.length;++r<u;){var o=n[r];if(t(o,r,n))return o
}}function Ft(n,t,r){if(t&&typeof r=="undefined"&&Xr(n)){r=-1;for(var e=n.length;++r<e&&false!==t(n[r],r,n););}else ft(n,t,r);return n}function Bt(n,t,r){var e=n,u=n?n.length:0;if(t=t&&typeof r=="undefined"?t:ut(t,r,3),Xr(n))for(;u--&&false!==t(n[u],u,n););else{if(typeof u!="number")var o=Zr(n),u=o.length;else Jr.unindexedChars&&Rt(n)&&(e=n.split(""));ft(e,function(r,a){return a=o?o[--u]:--u,t(e[a],a,n)})}return n}function Lt(n,t,r){var e=-1,u=n?n.length:0,o=ir(typeof u=="number"?u:0);if(t=v.createCallback(t,r,3),Xr(n))for(;++e<u;)o[e]=t(n[e],e,n);
else ft(n,function(n,r,u){o[++e]=t(n,r,u)});return o}function Wt(n,t,r){var u=-1/0,o=u;if(typeof t!="function"&&r&&r[t]===n&&(t=null),null==t&&Xr(n)){r=-1;for(var a=n.length;++r<a;){var i=n[r];i>o&&(o=i)}}else t=null==t&&Rt(n)?e:v.createCallback(t,r,3),ft(n,function(n,r,e){r=t(n,r,e),r>u&&(u=r,o=n)});return o}function zt(n,t,r,e){var u=3>arguments.length;if(t=v.createCallback(t,e,4),Xr(n)){var o=-1,a=n.length;for(u&&(r=n[++o]);++o<a;)r=t(r,n[o],o,n)}else ft(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)
else ft(n,function(n,r,u){o[++e]=t(n,r,u)});return o}function Wt(n,t,r){var u=-1/0,o=u;if(typeof t!="function"&&r&&r[t]===n&&(t=null),null==t&&Xr(n)){r=-1;for(var a=n.length;++r<a;){var i=n[r];i>o&&(o=i)}}else t=null==t&&Rt(n)?e:v.createCallback(t,r,3),ft(n,function(n,r,e){r=t(n,r,e),r>u&&(u=r,o=n)});return o}function zt(n,t,r,e){var u=3>arguments.length;if(t=v.createCallback(t,e,4),Xr(n)){var o=-1,a=n.length;for(u&&a&&(r=n[++o]);++o<a;)r=t(r,n[o],o,n)}else ft(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)
});return r}function Kt(n,t,r,e){var u=3>arguments.length;return t=v.createCallback(t,e,4),Bt(n,function(n,e,o){r=u?(u=false,n):t(r,n,e,o)}),r}function Mt(n){var t=-1,r=n?n.length:0,e=ir(typeof r=="number"?r:0);return Ft(n,function(n){var r=st(0,++t);e[t]=e[r],e[r]=n}),e}function Vt(n,t,r){var e;if(t=v.createCallback(t,r,3),Xr(n)){r=-1;for(var u=n.length;++r<u&&!(e=t(n[r],r,n)););}else ft(n,function(n,r,u){return!(e=t(n,r,u))});return!!e}function Ut(n,t,r){var e=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=-1;
for(t=v.createCallback(t,r,3);++o<u&&t(n[o],o,n);)e++}else if(e=t,null==e||r)return n?n[0]:h;return s(n,0,Mr(Kr(0,e),u))}function Gt(t,r,e){if(typeof e=="number"){var u=t?t.length:0;e=0>e?Kr(0,u+e):e||0}else if(e)return e=Jt(t,r),t[e]===r?e:-1;return n(t,r,e)}function Ht(n,t,r){if(typeof t!="number"&&null!=t){var e=0,u=-1,o=n?n.length:0;for(t=v.createCallback(t,r,3);++u<o&&t(n[u],u,n);)e++}else e=null==t||r?1:Kr(0,t);return s(n,e)}function Jt(n,t,r,e){var u=0,o=n?n.length:u;for(r=r?v.createCallback(r,e,1):tr,t=r(t);u<o;)e=u+o>>>1,r(n[e])<t?u=e+1:o=e;
return u}function Qt(n,t,r,e){return typeof t!="boolean"&&null!=t&&(e=r,r=typeof t!="function"&&e&&e[t]===n?null:t,t=false),null!=r&&(r=v.createCallback(r,e,3)),gt(n,t,r)}function Xt(){for(var n=1<arguments.length?arguments:arguments[0],t=-1,r=n?Wt(oe(n,"length")):0,e=ir(0>r?0:r);++t<r;)e[t]=oe(n,t);return e}function Yt(n,t){var r=-1,e=n?n.length:0,u={};for(t||!e||Xr(n[0])||(t=[]);++r<e;){var o=n[r];t?u[o]=t[r]:o&&(u[o[0]]=o[1])}return u}function Zt(n,t){return 2<arguments.length?vt(n,17,s(arguments,2),null,t):vt(n,1,null,null,t)

View File

@@ -82,7 +82,7 @@
* <a href="#_mapcollection-callbackidentity-thisarg">`_.map`</a>
* <a href="#_maxcollection-callbackidentity-thisarg">`_.max`</a>
* <a href="#_mincollection-callbackidentity-thisarg">`_.min`</a>
* <a href="#_pluckcollection-property">`_.pluck`</a>
* <a href="#_pluckcollection-prop">`_.pluck`</a>
* <a href="#_reducecollection-callbackidentity-accumulator-thisarg">`_.reduce`</a>
* <a href="#_reducerightcollection-callbackidentity-accumulator-thisarg">`_.reduceRight`</a>
* <a href="#_rejectcollection-callbackidentity-thisarg">`_.reject`</a>
@@ -1140,7 +1140,7 @@ _.isArray(squares.value());
<!-- div -->
### <a id="_chainvalue"></a>`_.chain(value)`
<a href="#_chainvalue">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6884 "View in source") [&#x24C9;][1]
<a href="#_chainvalue">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6885 "View in source") [&#x24C9;][1]
Creates a `lodash` object that wraps the given value with explicit method chaining enabled.
@@ -1174,7 +1174,7 @@ var youngest = _.chain(characters)
<!-- div -->
### <a id="_tapvalue-interceptor-thisarg"></a>`_.tap(value, interceptor, [thisArg])`
<a href="#_tapvalue-interceptor-thisarg">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6911 "View in source") [&#x24C9;][1]
<a href="#_tapvalue-interceptor-thisarg">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6912 "View in source") [&#x24C9;][1]
This method invokes `interceptor` and returns `value`. The interceptor is bound to `thisArg` and invoked with one argument; *(value)*. The purpose of this method is to "tap into" a method chain in order to perform operations on intermediate results within the chain.
@@ -1203,7 +1203,7 @@ _([1, 2, 3, 4])
<!-- div -->
### <a id="_prototypechain"></a>`_.prototype.chain()`
<a href="#_prototypechain">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6941 "View in source") [&#x24C9;][1]
<a href="#_prototypechain">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6942 "View in source") [&#x24C9;][1]
Enables explicit method chaining on the wrapper object.
@@ -1237,7 +1237,7 @@ _(characters).chain()
<!-- div -->
### <a id="_prototypetostring"></a>`_.prototype.toString()`
<a href="#_prototypetostring">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6958 "View in source") [&#x24C9;][1]
<a href="#_prototypetostring">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6959 "View in source") [&#x24C9;][1]
Produces the `toString` result of the wrapped value.
@@ -1258,7 +1258,7 @@ _([1, 2, 3]).toString();
<!-- div -->
### <a id="_prototypevalueof"></a>`_.prototype.valueOf()`
<a href="#_prototypevalueof">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6975 "View in source") [&#x24C9;][1]
<a href="#_prototypevalueof">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6976 "View in source") [&#x24C9;][1]
Extracts the wrapped value.
@@ -1858,14 +1858,14 @@ _.min(characters, 'age');
<!-- div -->
### <a id="_pluckcollection-property"></a>`_.pluck(collection, property)`
<a href="#_pluckcollection-property">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L4089 "View in source") [&#x24C9;][1]
### <a id="_pluckcollection-prop"></a>`_.pluck(collection, prop)`
<a href="#_pluckcollection-prop">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L4089 "View in source") [&#x24C9;][1]
Retrieves the value of a specified property from all elements in the collection.
#### Arguments
1. `collection` *(Array|Object|string)*: The collection to iterate over.
2. `property` *(string)*: The name of the property to pluck.
2. `prop` *(string)*: The name of the property to pluck.
#### Returns
*(Array)*: Returns a new array of property values.
@@ -4019,7 +4019,7 @@ _.values({ 'one': 1, 'two': 2, 'three': 3 });
<!-- div -->
### <a id="_now"></a>`_.now`
<a href="#_now">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6439 "View in source") [&#x24C9;][1]
<a href="#_now">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6440 "View in source") [&#x24C9;][1]
*(unknown)*: Gets the number of milliseconds that have elapsed since the Unix epoch *(1 January `1970 00`:00:00 UTC)*.
@@ -4154,9 +4154,9 @@ _.identity(object) === object;
<!-- div -->
### <a id="_matchprops"></a>`_.match(props)`
<a href="#_matchprops">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6293 "View in source") [&#x24C9;][1]
<a href="#_matchprops">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6294 "View in source") [&#x24C9;][1]
Creates a "_.where" style function, which returns `true` for a given object if it has the equivalent property values of the `props` object, else `false`.
Creates a "_.where" style function, which performs a deep comparison between a given object and the `props` object, returning `true` if the given object has equivalent property values, else `false`.
#### Arguments
1. `props` *(Object)*: The object of property values to match.
@@ -4188,7 +4188,7 @@ _.find(characters, matchAge);
<!-- div -->
### <a id="_mixinobjectlodash-source-options"></a>`_.mixin([object=lodash], source, [options])`
<a href="#_mixinobjectlodash-source-options">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6349 "View in source") [&#x24C9;][1]
<a href="#_mixinobjectlodash-source-options">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6350 "View in source") [&#x24C9;][1]
Adds function properties of a source object to the destination object. If `object` is a function methods will be added to its prototype as well.
@@ -4224,7 +4224,7 @@ _('fred').capitalize();
<!-- div -->
### <a id="_noconflict"></a>`_.noConflict()`
<a href="#_noconflict">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6405 "View in source") [&#x24C9;][1]
<a href="#_noconflict">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6406 "View in source") [&#x24C9;][1]
Reverts the '_' variable to its previous value and returns a reference to the `lodash` function.
@@ -4244,7 +4244,7 @@ var lodash = _.noConflict();
<!-- div -->
### <a id="_noop"></a>`_.noop()`
<a href="#_noop">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6422 "View in source") [&#x24C9;][1]
<a href="#_noop">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6423 "View in source") [&#x24C9;][1]
A no-operation function.
@@ -4263,7 +4263,7 @@ _.noop(object) === undefined;
<!-- div -->
### <a id="_parseintvalue-radix"></a>`_.parseInt(value, [radix])`
<a href="#_parseintvalue-radix">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6463 "View in source") [&#x24C9;][1]
<a href="#_parseintvalue-radix">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6464 "View in source") [&#x24C9;][1]
Converts the given value into an integer of the specified radix. If `radix` is `undefined` or `0` a `radix` of `10` is used unless the `value` is a hexadecimal, in which case a `radix` of `16` is used.
@@ -4290,7 +4290,7 @@ _.parseInt('08');
<!-- div -->
### <a id="_propertykey"></a>`_.property(key)`
<a href="#_propertykey">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6492 "View in source") [&#x24C9;][1]
<a href="#_propertykey">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6493 "View in source") [&#x24C9;][1]
Creates a "_.pluck" style function, which returns the `key` value of a given object.
@@ -4324,7 +4324,7 @@ _.sortBy(characters, getName);
<!-- div -->
### <a id="_randommin0-max1-floatingfalse"></a>`_.random([min=0], [max=1], [floating=false])`
<a href="#_randommin0-max1-floatingfalse">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6525 "View in source") [&#x24C9;][1]
<a href="#_randommin0-max1-floatingfalse">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6526 "View in source") [&#x24C9;][1]
Produces a random number between `min` and `max` *(inclusive)*. If only one argument is provided a number between `0` and the given number will be returned. If `floating` is truey or either `min` or `max` are floats a floating-point number will be returned instead of an integer.
@@ -4359,7 +4359,7 @@ _.random(1.2, 5.2);
<!-- div -->
### <a id="_resultobject-key"></a>`_.result(object, key)`
<a href="#_resultobject-key">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6583 "View in source") [&#x24C9;][1]
<a href="#_resultobject-key">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6584 "View in source") [&#x24C9;][1]
Resolves the value of property `key` on `object`. If `key` is a function it will be invoked with the `this` binding of `object` and its result returned, else the property value is returned. If `object` is falsey then `undefined` is returned.
@@ -4412,7 +4412,7 @@ Create a new `lodash` function using the given context object.
<!-- div -->
### <a id="_templatetext-data-options"></a>`_.template(text, data, [options])`
<a href="#_templatetext-data-options">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6676 "View in source") [&#x24C9;][1]
<a href="#_templatetext-data-options">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6677 "View in source") [&#x24C9;][1]
A micro-templating method that handles arbitrary delimiters, preserves whitespace, and correctly escapes quotes within interpolated code.
@@ -4504,7 +4504,7 @@ fs.writeFileSync(path.join(cwd, 'jst.js'), '\
<!-- div -->
### <a id="_timesn-callback-thisarg"></a>`_.times(n, callback, [thisArg])`
<a href="#_timesn-callback-thisarg">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6799 "View in source") [&#x24C9;][1]
<a href="#_timesn-callback-thisarg">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6800 "View in source") [&#x24C9;][1]
Executes the callback `n` times, returning an array of the results of each callback execution. The callback is bound to `thisArg` and invoked with one argument; *(index)*.
@@ -4536,7 +4536,7 @@ _.times(3, function(n) { this.cast(n); }, mage);
<!-- div -->
### <a id="_unescapestring"></a>`_.unescape(string)`
<a href="#_unescapestring">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6829 "View in source") [&#x24C9;][1]
<a href="#_unescapestring">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6830 "View in source") [&#x24C9;][1]
The inverse of `_.escape`; this method converts the HTML entities `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to their corresponding characters.
@@ -4562,7 +4562,7 @@ _.unescape('Fred, Barney &amp; Pebbles');
<!-- div -->
### <a id="_uniqueidprefix"></a>`_.uniqueId([prefix])`
<a href="#_uniqueidprefix">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6853 "View in source") [&#x24C9;][1]
<a href="#_uniqueidprefix">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L6854 "View in source") [&#x24C9;][1]
Generates a unique ID. If `prefix` is provided the ID will be appended to it.
@@ -4615,7 +4615,7 @@ A reference to the `lodash` function.
<!-- div -->
### <a id="_version"></a>`_.VERSION`
<a href="#_version">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L7176 "View in source") [&#x24C9;][1]
<a href="#_version">#</a> [&#x24C8;](https://github.com/lodash/lodash/blob/master/lodash.js#L7177 "View in source") [&#x24C9;][1]
*(string)*: The semantic version number.

View File

@@ -4126,7 +4126,7 @@
var index = -1,
length = collection.length;
if (noaccum) {
if (noaccum && length) {
accumulator = collection[++index];
}
while (++index < length) {

View File

@@ -6367,6 +6367,20 @@
var actual = func([], noop, undefined);
strictEqual(actual, undefined);
});
test('`_.' + methodName + '` should return `undefined` for empty collections when no `accumulator` is provided (test in IE > 9 and modern browsers)', 2, function() {
var array = [],
object = { '0': 1, 'length': 0 };
if ('__proto__' in array) {
array.__proto__ = object;
strictEqual(_.reduce(array, noop), undefined);
}
else {
skipTest();
}
strictEqual(_.reduce(object, noop), undefined);
});
});
/*--------------------------------------------------------------------------*/