mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-01-31 15:27:50 +00:00
Improve compliance with Array methods in ES5 when passed a null value. (ES5 Array methods treat null like [])
This commit is contained in:
@@ -83,6 +83,7 @@ $(document).ready(function() {
|
||||
equals(_.indexOf(numbers, 2), 1, 'can compute indexOf, even without the native function');
|
||||
var result = (function(){ return _.indexOf(arguments, 2); })(1, 2, 3);
|
||||
equals(result, 1, 'works on an arguments object');
|
||||
equals(_.indexOf(null, 2), -1, 'handles nulls properly');
|
||||
});
|
||||
|
||||
test("arrays: lastIndexOf", function() {
|
||||
@@ -92,6 +93,7 @@ $(document).ready(function() {
|
||||
equals(_.lastIndexOf(numbers, 0), 8, 'lastIndexOf the other element');
|
||||
var result = (function(){ return _.lastIndexOf(arguments, 1); })(1, 0, 1, 0, 0, 1, 0, 0, 0);
|
||||
equals(result, 5, 'works on an arguments object');
|
||||
equals(_.indexOf(null, 2), -1, 'handles nulls properly');
|
||||
});
|
||||
|
||||
test("arrays: range", function() {
|
||||
|
||||
@@ -29,6 +29,10 @@ $(document).ready(function() {
|
||||
answers = [];
|
||||
_.each({range : 1, speed : 2, length : 3}, function(v){ answers.push(v); });
|
||||
ok(answers.join(', '), '1, 2, 3', 'can iterate over objects with numeric length properties');
|
||||
|
||||
answers = 0;
|
||||
_.each(null, function(){ ++answers; });
|
||||
equals(answers, 0, 'handles a null properly');
|
||||
});
|
||||
|
||||
test('collections: map', function() {
|
||||
@@ -46,6 +50,9 @@ $(document).ready(function() {
|
||||
|
||||
var ids = _.map(document.images, function(n){ return n.id; });
|
||||
ok(ids[0] == 'chart_image', 'can use collection methods on HTMLCollections');
|
||||
|
||||
var ifnull = _.map(null, function(){});
|
||||
ok(_.isArray(ifnull) && ifnull.length === 0, 'handles a null properly');
|
||||
});
|
||||
|
||||
test('collections: reduce', function() {
|
||||
@@ -64,6 +71,16 @@ $(document).ready(function() {
|
||||
|
||||
var sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num; });
|
||||
equals(sum, 6, 'default initial value');
|
||||
|
||||
var ifnull;
|
||||
try {
|
||||
_.reduce(null, function(){});
|
||||
} catch (ex) {
|
||||
ifnull = ex;
|
||||
}
|
||||
ok(ifnull instanceof TypeError, 'handles a null (without inital value) properly');
|
||||
|
||||
ok(_.reduce(null, function(){}, 138) === 138, 'handles a null (with initial value) properly');
|
||||
});
|
||||
|
||||
test('collections: reduceRight', function() {
|
||||
@@ -75,6 +92,16 @@ $(document).ready(function() {
|
||||
|
||||
var list = _.foldr(["foo", "bar", "baz"], function(memo, str){ return memo + str; });
|
||||
equals(list, 'bazbarfoo', 'default initial value');
|
||||
|
||||
var ifnull;
|
||||
try {
|
||||
_.reduceRight(null, function(){});
|
||||
} catch (ex) {
|
||||
ifnull = ex;
|
||||
}
|
||||
ok(ifnull instanceof TypeError, 'handles a null (without inital value) properly');
|
||||
|
||||
ok(_.reduceRight(null, function(){}, 138) === 138, 'handles a null (with initial value) properly');
|
||||
});
|
||||
|
||||
test('collections: detect', function() {
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
// Delegates to **ECMAScript 5**'s native `forEach` if available.
|
||||
var each = _.each = _.forEach = function(obj, iterator, context) {
|
||||
var value;
|
||||
if (obj == null) return;
|
||||
if (nativeForEach && obj.forEach === nativeForEach) {
|
||||
obj.forEach(iterator, context);
|
||||
} else if (_.isNumber(obj.length)) {
|
||||
@@ -86,8 +87,9 @@
|
||||
// Return the results of applying the iterator to each element.
|
||||
// Delegates to **ECMAScript 5**'s native `map` if available.
|
||||
_.map = function(obj, iterator, context) {
|
||||
if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
|
||||
var results = [];
|
||||
if (obj == null) return results;
|
||||
if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
|
||||
each(obj, function(value, index, list) {
|
||||
results[results.length] = iterator.call(context, value, index, list);
|
||||
});
|
||||
@@ -98,6 +100,7 @@
|
||||
// or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
|
||||
_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
|
||||
var initial = memo !== void 0;
|
||||
if (obj == null) obj = [];
|
||||
if (nativeReduce && obj.reduce === nativeReduce) {
|
||||
if (context) iterator = _.bind(iterator, context);
|
||||
return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
|
||||
@@ -105,16 +108,19 @@
|
||||
each(obj, function(value, index, list) {
|
||||
if (!initial && index === 0) {
|
||||
memo = value;
|
||||
initial = true;
|
||||
} else {
|
||||
memo = iterator.call(context, memo, value, index, list);
|
||||
}
|
||||
});
|
||||
if (!initial) throw new TypeError("Reduce of empty array with no initial value");
|
||||
return memo;
|
||||
};
|
||||
|
||||
// The right-associative version of reduce, also known as `foldr`.
|
||||
// Delegates to **ECMAScript 5**'s native `reduceRight` if available.
|
||||
_.reduceRight = _.foldr = function(obj, iterator, memo, context) {
|
||||
if (obj == null) obj = [];
|
||||
if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
|
||||
if (context) iterator = _.bind(iterator, context);
|
||||
return memo !== void 0 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
|
||||
@@ -139,8 +145,9 @@
|
||||
// Delegates to **ECMAScript 5**'s native `filter` if available.
|
||||
// Aliased as `select`.
|
||||
_.filter = _.select = function(obj, iterator, context) {
|
||||
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
|
||||
var results = [];
|
||||
if (obj == null) return results;
|
||||
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
|
||||
each(obj, function(value, index, list) {
|
||||
if (iterator.call(context, value, index, list)) results[results.length] = value;
|
||||
});
|
||||
@@ -150,6 +157,7 @@
|
||||
// Return all the elements for which a truth test fails.
|
||||
_.reject = function(obj, iterator, context) {
|
||||
var results = [];
|
||||
if (obj == null) return results;
|
||||
each(obj, function(value, index, list) {
|
||||
if (!iterator.call(context, value, index, list)) results[results.length] = value;
|
||||
});
|
||||
@@ -161,8 +169,9 @@
|
||||
// Aliased as `all`.
|
||||
_.every = _.all = function(obj, iterator, context) {
|
||||
iterator = iterator || _.identity;
|
||||
if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
|
||||
var result = true;
|
||||
if (obj == null) return result;
|
||||
if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
|
||||
each(obj, function(value, index, list) {
|
||||
if (!(result = result && iterator.call(context, value, index, list))) return breaker;
|
||||
});
|
||||
@@ -174,8 +183,9 @@
|
||||
// Aliased as `any`.
|
||||
var any = _.some = _.any = function(obj, iterator, context) {
|
||||
iterator = iterator || _.identity;
|
||||
if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
|
||||
var result = false;
|
||||
if (obj == null) return result;
|
||||
if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
|
||||
each(obj, function(value, index, list) {
|
||||
if (result = iterator.call(context, value, index, list)) return breaker;
|
||||
});
|
||||
@@ -185,8 +195,9 @@
|
||||
// Determine if a given value is included in the array or object using `===`.
|
||||
// Aliased as `contains`.
|
||||
_.include = _.contains = function(obj, target) {
|
||||
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
|
||||
var found = false;
|
||||
if (obj == null) return found;
|
||||
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
|
||||
any(obj, function(value) {
|
||||
if (found = value === target) return true;
|
||||
});
|
||||
@@ -346,6 +357,7 @@
|
||||
// item in an array, or -1 if the item is not included in the array.
|
||||
// Delegates to **ECMAScript 5**'s native `indexOf` if available.
|
||||
_.indexOf = function(array, item) {
|
||||
if (array == null) return -1;
|
||||
if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
|
||||
for (var i = 0, l = array.length; i < l; i++) if (array[i] === item) return i;
|
||||
return -1;
|
||||
@@ -354,6 +366,7 @@
|
||||
|
||||
// Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
|
||||
_.lastIndexOf = function(array, item) {
|
||||
if (array == null) return -1;
|
||||
if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
|
||||
var i = array.length;
|
||||
while (i--) if (array[i] === item) return i;
|
||||
|
||||
Reference in New Issue
Block a user