Repository: jashkenas/underscore
Pull request #2779 (2018-09-05 14:23:51)

fixed return undefined in first and last with guard
Old behavior:
`_([[1, 2, 3], [], [1, 2, 3]]).map(_.first) // [1, [], 1]`

New behavior:
`_([[1, 2, 3], [], [1, 2, 3]]).map(_.first) // [1, undefined, 1]`


Patch:
diff --git a/underscore.js b/underscore.js
index 8219dc5..50a618c 100644
--- a/underscore.js
+++ b/underscore.js
@@ -497,7 +497,7 @@
   // values in the array. Aliased as `head` and `take`. The **guard** check
   // allows it to work with `_.map`.
   _.first = _.head = _.take = function(array, n, guard) {
-    if (array == null || array.length < 1) return n == null ? void 0 : [];
+    if (array == null || array.length < 1) return n == null || guard ? void 0 : [];
     if (n == null || guard) return array[0];
     return _.initial(array, array.length - n);
   };
@@ -512,7 +512,7 @@
   // Get the last element of an array. Passing **n** will return the last N
   // values in the array.
   _.last = function(array, n, guard) {
-    if (array == null || array.length < 1) return n == null ? void 0 : [];
+    if (array == null || array.length < 1) return n == null || guard ? void 0 : [];
     if (n == null || guard) return array[array.length - 1];
     return _.rest(array, Math.max(0, array.length - n));
   };


Test patch:
diff --git a/test/arrays.js b/test/arrays.js
index 86392ed..b89f2b8 100644
--- a/test/arrays.js
+++ b/test/arrays.js
@@ -12,8 +12,8 @@
     assert.deepEqual(_.first([1, 2, 3], 5), [1, 2, 3], 'returns the whole array if n > length');
     var result = (function(){ return _.first(arguments); }(4, 3, 2, 1));
     assert.strictEqual(result, 4, 'works on an arguments object');
-    result = _.map([[1, 2, 3], [1, 2, 3]], _.first);
-    assert.deepEqual(result, [1, 1], 'works well with _.map');
+    result = _.map([[1, 2, 3], [], [1, 2, 3]], _.first);
+    assert.deepEqual(result, [1, void 0, 1], 'works well with _.map');
     assert.strictEqual(_.first(null), void 0, 'returns undefined when called on null');
     assert.deepEqual(_.first([], 10), [], 'returns an empty array when called with an explicit number of elements to return');
     assert.deepEqual(_.first([], 1), [], 'returns an empty array when called with an explicit number of elements to return');
@@ -70,10 +70,9 @@
     assert.deepEqual(_.last([1, 2, 3], 5), [1, 2, 3], 'returns the whole array if n > length');
     var result = (function(){ return _(arguments).last(); }(1, 2, 3, 4));
     assert.strictEqual(result, 4, 'works on an arguments object');
-    result = _.map([[1, 2, 3], [1, 2, 3]], _.last);
-    assert.deepEqual(result, [3, 3], 'works well with _.map');
+    result = _.map([[1, 2, 3], [], [1, 2, 3]], _.last);
+    assert.deepEqual(result, [3, void 0, 3], 'works well with _.map');
     assert.strictEqual(_.last(null), void 0, 'returns undefined when called on null');
-
     assert.deepEqual(_.last([], 10), [], 'returns an empty array when called with an explicit number of elements to return');
     assert.deepEqual(_.last([], 1), [], 'returns an empty array when called with an explicit number of elements to return');
     assert.deepEqual(_.last(null, 5), [], 'returns an empty array when called with an explicit number of elements to return');