Javascript _.map() против array.map(); почему один работает здесь, а другой нет?

Почему функция reverse2 с использованием _.map() работает, а arr.map() в этой ситуации не работает? Есть ли проблема с синтаксисом? Я не смог понять это.

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]

person jmancherje    schedule 18.08.2015    source источник
comment
Никогда не изменяйте массив во время его итерации. Или ожидать, что что-нибудь будет работать так.   -  person Bergi    schedule 18.08.2015
comment
Собственный метод map перепрыгивает через дыры. Поэтому не удаляйте из него элементы.   -  person Bergi    schedule 18.08.2015
comment
похоже, что _.map не дублирует массив перед передачей его обратному вызову, как это делает OEM. у него также есть несколько других несоответствий, но они позволяют работать намного быстрее, чем родной.   -  person dandavis    schedule 18.08.2015


Ответы (2)


Array.prototype.map

Это сложный вопрос. Чтобы объяснить, почему Array.prototype.map ведет себя так: нам нужно проверить спецификацию. Так:

  1. Пусть O будет результатом вызова ToObject с передачей значения this в качестве аргумента.
  2. Пусть lenValue будет результатом вызова внутреннего метода [[Get]] для O с аргументом "length".
  3. Пусть len будет ToUint32(lenValue).
  4. Если IsCallable(callbackfn) имеет значение false, генерируется исключение TypeError.
  5. Если был предоставлен thisArg, пусть T будет thisArg; иначе пусть T будет undefined.
  6. Пусть A будет новым массивом, созданным как бы с помощью выражения new Array(len), где Array — это стандартный встроенный конструктор с таким именем. а len — значение len. ...

Важными моментами, на которые следует обратить внимание, являются № 2 и № 6. Из них видно, что map создает новый массив с той же длиной, что и исходный.

Затем еще одна вещь из того же раздела о методе:

... Если существующие элементы массива изменены, их значение, переданное callbackfn, будет значением во время их посещения картой; элементы, которые удаляются после начала вызова map и до посещения, не посещаются.

И это дает ответ на ваш вопрос: карта создаст массив той же длины, но поскольку в функции итерации вы удаляете элементы из исходного массива (с pop), новый массив заполняется только второй половиной оригинала.

_.карта

Почему функция Underscore _.map ведет себя по-другому? Потому что его реализация перебирает все элементы исходного массива. Отсюда и разница.

person dfsq    schedule 18.08.2015

person    schedule
comment
Вы не указываете, как это отвечает на вопрос. - person Aaron; 27.12.2016
comment
Это объясняет, почему array.map не работает, он мог бы сделать лучшее введение для таких людей, как вы, но это нормально. - person MalachiteBR; 19.12.2017