Why does the reverse2 function using _.map() work, but the arr.map() doesn't work in this situation? Is there a syntax problem? I haven't been able to figure it out.
function reverse2(arr){
return _.map(arr, function(val,index, arr1){return arr1.pop();});
}
console.log(reverse2([1,2,3,4,5,6])); // logs [6,5,4,3,2,1]
function reverse3(arr){
return arr.map(function(val,index, arr1){return arr1.pop();});
}
console.log(reverse3([1,2,3,4,5,6])); // logs [6,5,4,undefined, undefined, undefined]
Why does the reverse2 function using _.map() work, but the arr.map() doesn't work in this situation? Is there a syntax problem? I haven't been able to figure it out.
function reverse2(arr){
return _.map(arr, function(val,index, arr1){return arr1.pop();});
}
console.log(reverse2([1,2,3,4,5,6])); // logs [6,5,4,3,2,1]
function reverse3(arr){
return arr.map(function(val,index, arr1){return arr1.pop();});
}
console.log(reverse3([1,2,3,4,5,6])); // logs [6,5,4,undefined, undefined, undefined]
Share
Improve this question
asked Aug 18, 2015 at 16:52
jmancherjejmancherje
6,6438 gold badges38 silver badges59 bronze badges
3
- 2 Never ever modify an array while iterating it. Or expect anything to work like that. – Bergi Commented Aug 18, 2015 at 17:15
-
The native
map
method jumps over holes. So don't delete elements from it. – Bergi Commented Aug 18, 2015 at 17:18 - looks like _.map doesn't dupe the array before passing it to the callback, like the OEM does. it has a few other non-conformities as well, but they allow a much faster operation than the native. – dandavis Commented Aug 18, 2015 at 17:31
2 Answers
Reset to default 5Array.prototype.map
This is tricky question. To explain why Array.prototype.map behaves this way we need to check specification. So:
- Let O be the result of calling ToObject passing the this value as the argument.
- Let lenValue be the result of calling the [[Get]] internal method of O with the argument "length".
- Let len be ToUint32(lenValue).
- If IsCallable(callbackfn) is false, throw a TypeError exception.
- If thisArg was supplied, let T be thisArg; else let T be undefined.
- Let A be a new array created as if by the expression new Array(len) where Array is the standard built-in constructor with that name and len is the value of len. ...
The important points here to pay attention are #2 and #6. From them it's obvious that map
creates a new array with the same length as the original one.
Then another thing from the same section about method:
... If existing elements of the array are changed, their value as passed to callbackfn will be the value at the time map visits them; elements that are deleted after the call to map begins and before being visited are not visited.
And it gives the answer to your question: map will create an array of the same length but since in iteration function you are removing elements from original array (with pop
), new array populated with only second half of the original.
_.map
Why Underscore _.map
function behave differently? Because the implementation of it iterates over all items of the original array. Hence the difference.
array.map
first call: [1,2,3,4,5,6], position 0 hash value '1', so pop 6.
seconde call: [1,2,3,4,5], position 1 hash value '2', so pop 5.
third call: [1,2,3,4], position 2 hash value '3', so pop 4.
fourth call: [1,2,3], position 3 hash no value, so pop nothing.