Единственная разница, которую я вижу в map и foreach, заключается в том, что map
она возвращает массив, а forEach
не возвращает . Однако я даже не понимаю последнюю строчку forEach
метода " func.call(scope, this[i], i, this);
". Например, не « this
» и « scope
» со ссылкой на тот же объект и не является , this[i]
и со i
ссылкой на текущее значение в цикле?
Я заметил, что в другом посте кто-то сказал: «Используйте, forEach
когда вы хотите что-то сделать на основе каждого элемента списка. Например, вы можете добавлять что-то на страницу. По сути, это отлично подходит, когда вам нужны« побочные эффекты ». Я не знаю, что подразумевается под побочными эффектами.
Array.prototype.map = function(fnc) {
var a = new Array(this.length);
for (var i = 0; i < this.length; i++) {
a[i] = fnc(this[i]);
}
return a;
}
Array.prototype.forEach = function(func, scope) {
scope = scope || this;
for (var i = 0, l = this.length; i < l; i++) {
func.call(scope, this[i], i, this);
}
}
Наконец, есть ли какое-либо реальное использование этих методов в javascript (поскольку мы не обновляем базу данных), кроме как манипулировать числами, подобными этому:
alert([1,2,3,4].map(function(x){ return x + 1})); //this is the only example I ever see of map in javascript.
Спасибо за любой ответ.
источник
map
иforEach
? Все, что я получаю от Google, - это спецификации использования и руководства.Ответы:
Существенная разница между
map
иforEach
в вашем примере заключается в том, что онforEach
работает с исходными элементами массива, тогдаmap
как в результате явно возвращает новый массив.С помощью
forEach
вы выполняете некоторые действия с каждым элементом исходного массива и при необходимости изменяете его.forEach
Метод запускает функцию , которую Вы предоставили для каждого элемента, но ничего не возвращает (undefined
). С другой стороны,map
проходит по массиву, применяет функцию к каждому элементу и выдает результат в виде нового массива ."Побочный эффект"
forEach
заключается в том, что исходный массив изменяется. «Без побочного эффекта»map
означает, что при идиоматическом использовании исходные элементы массива не меняются; новый массив - это взаимно-однозначное сопоставление каждого элемента в исходном массиве - преобразование сопоставления является вашей предоставленной функцией.Тот факт, что база данных не задействована, не означает, что вам не придется работать со структурами данных, что, в конце концов, является одной из сущностей программирования на любом языке. Что касается вашего последнего вопроса, ваш массив может содержать не только числа, но и объекты, строки, функции и т. Д.
источник
.map
может делать все, что.forEach
умеет (включая изменение элементов), просто возвращает новый список, созданный с помощью функции итератора..map()
создает новый массив и не изменяет оригинал. Вы действительно можете изменить массив, который сам отображается, но это было бы по крайней мере неидиоматично, если не бессмысленно..forEach()
, хотя и похоже, применяет свою функцию к каждому элементу, но всегда возвращаетundefined
. Несмотря на все вышесказанное, ОП также спрашивает о своих собственных специфических функциях, добавленных в прототип массива; раньше здесь не было ES5.forEach
, с чем вы не могли бы сделатьmap
. Вы можете просто не заботиться о возвращаемом значении,map
и у вас будетforEach
. Разница в том, что его очень неэффективно использоватьmap
для задач, в которых вы не хотите создавать новый массив на основе результатов. Так что для них вы используетеforEach
.for
цикла. Я не возражаю, что есть некоторая разница в «эффективности», но я также не думаю, что кто-то спорит, что у одного есть магия, которую другой каким-то образом не может достичь. Хотя на самом деле есть одна вещь, которуюmap
нельзя сделать: не возвращать массив. Там это значение в том , JS оправдала ожидания от других языков, на поведение функциональных фаворитов , какmap
,reduce
,filter
и т.д. Например, вы могли бы реализовать сreduceRight
использованием аналогичных строительных блоков, но почему бы не использоватьreduceRight
?b.val = b.val**2
внутри возвращенного объекта . То, что мы говорим, действительно возможно, но сбивает с толку и не является идиоматическим. Обычно вы просто возвращаете новое значение, а не присваиваете его также исходному массиву:a=[{val:1},{val:2},{val:3},{val:4}]; a.map((b)=>{b.val**2}); JSON.stringify(a);
Основное различие между этими двумя методами - концептуальное и стилистическое: вы используете,
forEach
когда хотите что-то сделать с каждым элементом массива или с каждым элементом массива (я думаю, что выполнение «с» - это то, что цитируемый вами пост означает «побочные эффекты») , тогда как вы используете,map
когда хотите скопировать и преобразовать каждый элемент массива (без изменения оригинала).Поскольку оба
map
иforEach
вызывают функцию для каждого элемента в массиве, и эта функция определяется пользователем, вы почти ничего не можете сделать с одним, а не с другим. Возможно, хотя и некрасиво, использоватьmap
для изменения массива на месте и / или делать что-то с элементами массива:var a = [{ val: 1 }, { val: 2 }, { val: 3 }]; a.map(function(el) { el.val++; // modify element in-place alert(el.val); // do something with each element }); // a now contains [{ val: 2 }, { val: 3 }, { val: 4 }]
но гораздо чище и очевиднее в отношении вашего намерения использовать
forEach
:var a = [{ val: 1 }, { val: 2 }, { val: 3 }]; a.forEach(function(el) { el.val++; alert(el.val); });
Особенно, если, как это обычно бывает в реальном мире,
el
переменная полезна для чтения человеком:cats.forEach(function(cat) { cat.meow(); // nicer than cats[x].meow() });
Таким же образом вы можете легко использовать
forEach
для создания нового массива:var a = [1,2,3], b = []; a.forEach(function(el) { b.push(el+1); }); // b is now [2,3,4], a is unchanged
но чище использовать
map
:var a = [1,2,3], b = a.map(function(el) { return el+1; });
Также обратите внимание, что, поскольку
map
создается новый массив, он, вероятно, вызывает по крайней мере некоторое снижение производительности / памяти, когда все, что вам нужно, это итерация, особенно для больших массивов - см. Http://jsperf.com/map-foreachЧто касается того, почему вы хотите использовать эти функции, они полезны в любое время, когда вам нужно выполнять манипуляции с массивами в javascript, что (даже если мы просто говорим о javascript в среде браузера) довольно часто, почти в любое время вы обращаетесь к массиву, который не записываете вручную в коде. Возможно, вы имеете дело с массивом элементов DOM на странице или данными, полученными из запроса AJAX, или данными, введенными в форму пользователем. Один из распространенных примеров, с которыми я сталкиваюсь, - это извлечение данных из внешнего API, где вы, возможно, захотите использовать
map
для преобразования данных вforEach
нужный формат, а затем использовать для итерации по вашему новому массиву, чтобы отобразить его вашему пользователю.источник
.map()
все время используют для изменения встроенных элементов. Я был под впечатлением , что было главным преимуществом использования.map
более.forEach
.map
может изменять элементы, да, но это создаст массив, который вам не нужен. Вам также следует подумать о том, как выбор того или другого позволяет читателю угадать, есть ли у вас побочные эффекты,Проголосованный ответ (от Кена Редлера) вводит в заблуждение.
Побочный эффект в информатике означает, что свойство функции / метода изменяет глобальное состояние [wiki] . В некотором узком смысле это может также включать чтение из глобального состояния, а не из аргументов. В императивном или объектно-ориентированном программировании побочные эффекты проявляются чаще всего. И вы, вероятно, используете это, даже не осознавая.
Существенная разница между
forEach
иmap
заключается в том, чтоmap
выделяет память и сохраняет возвращаемое значение, аforEach
выбрасывает его. См. Спецификацию emca для получения дополнительной информации.Что касается причины, по которой люди говорят,
forEach
что используется, когда вам нужен побочный эффект, это то, что возвращаемое значениеforEach
всегдаundefined
. Если у него нет побочного эффекта (не меняет глобальное состояние), то функция просто тратит время процессора. Оптимизирующий компилятор устранит этот блок кода и заменит его окончательным значением (undefined
).Кстати, следует отметить, что JavaScript не имеет ограничений на побочные эффекты. Вы все еще можете изменить исходный массив внутри
map
.var a = [1,2,3]; //original var b = a.map( function(x,i){a[i] = 2*x; return x+1} ); console.log("modified=%j\nnew array=%j",a,b); // output: // modified=[2,4,6] // new array=[2,3,4]
источник
Это красивый вопрос с неожиданным ответом.
Следующее основано на официальном описании
Array.prototype.map()
.Нет ничего, что
forEach()
можно сделать, чегоmap()
нельзя. То есть,map()
является строгим супер-набор изforEach()
.Хотя
map()
обычно используется для создания нового массива, его также можно использовать для изменения текущего массива. Следующий пример иллюстрирует это:var a = [0, 1, 2, 3, 4], mapped = null; mapped = a.map(function (x) { a[x] = x*x*x; return x*x; }); console.log(mapped); // logs [0, 1, 4, 9, 16] As expected, these are squares. console.log(a); // logs [0, 1, 8, 27, 64] These are cubes of the original array!!
В приведенном выше примере
a
было удобно установитьa[i] === i
дляi < a.length
. Тем не менее, он демонстрирует мощьmap()
и, в частности, его способность изменять массив, для которого он вызывается.Примечание1:
официальное описание подразумевает, что
map()
может даже измениться длина массива, на котором он вызывается! Однако я не вижу (веских) причин для этого.Примечание 2:
несмотря на то, что
map()
карта является супернаборомforEach()
,forEach()
ее все равно следует использовать там, где требуется изменить данный массив. Это проясняет ваши намерения.Надеюсь, это помогло.
источник
mapped = a.map(function (x, i, arr) { arr[i] = x * x * x; return x * x; });.
a.forEach(function(x, i, arr) { ...
, что, опять же, концептуально более верный способ, когда вы намерены изменить каждый исходный элемент, а не отображать значения из одного массива в другойВы можете использовать
map
как если бы это былоforEach
.Однако он сделает больше, чем должен.
scope
может быть произвольным объектом; это ни в коем случае не обязательноthis
.Что касается того, есть ли реальное использование для
map
иforEach
, а также спросить, есть ли реальное использование для цикловfor
илиwhile
.источник
scope = scope || this
означает «еслиscope
ложно (undefined, null, false и т. д.),this
вместо этого установите область действия и продолжайте».Хотя все предыдущие вопросы верны, я бы определенно провел другое различие. Использование
map
иforEach
может подразумевать намерение.Мне нравится использовать,
map
когда я просто каким-то образом преобразую существующие данные (но хочу убедиться, что исходные данные не изменились.Мне нравится использовать,
forEach
когда я модифицирую коллекцию на месте.Например,
var b = [{ val: 1 }, { val: 2 }, { val: 3 }]; var c = b.map(function(el) { return { val: el.val + 1 }; // modify element in-place }); console.log(b); // [{ val: 1 }, { val: 2 }, { val: 3 }] console.log(c); // [{ val: 3 }, { val: 4 }, { val: 5 }]
Мое практическое правило заключается в том, чтобы убедиться, что
map
вы всегда создаете какой-то новый объект / значение для возврата для каждого элемента исходного списка и возвращаете его, а не просто выполняете какую-либо операцию с каждым элементом.Если у вас нет реальной необходимости изменять существующий список, нет смысла изменять его на месте, и он лучше подходит для функциональных / неизменяемых стилей программирования.
источник
TL; DR ответ -
map всегда возвращает другой массив.
forEach - нет. Вам решать, что он делает. Верните массив, если хотите, или сделайте что-нибудь еще, если нет.
Гибкость желательна в определенных ситуациях. Если это не то, с чем вы имеете дело, используйте карту.
источник
И снова я чувствую себя некромантом, добавляющим ответ на вопрос, который был задан 5 лет назад (к счастью, активность была довольно недавняя, так что я не единственный, кто тревожит мертвых :).
Другие уже писали о вашем главном вопросе относительно разницы между функциями. Но для...
... забавно спросить. Буквально сегодня я написал фрагмент кода, который присваивает несколько значений из регулярного выражения нескольким переменным, используя карту для преобразования. Он использовался для преобразования очень сложной текстовой структуры в визуализируемые данные ... но для простоты я предлагаю пример с использованием строк даты, потому что они, вероятно, более знакомы всем (хотя, если бы моя проблема действительно была с датами , вместо map я бы использовал Date-объект, который бы отлично справился со своей задачей).
const DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\.(\d{3})Z$/; const TEST_STRING = '2016-01-04T03:20:00.000Z'; var [ iYear, iMonth, iDay, iHour, iMinute, iSecond, iMillisecond ] = DATE_REGEXP // We take our regular expression and... .exec(TEST_STRING) // ...execute it against our string (resulting in an array of matches)... .slice(1) // ...drop the 0th element from those (which is the "full string match")... .map(value => parseInt(value, 10)); // ...and map the rest of the values to integers... // ...which we now have as individual variables at our perusal console.debug('RESULT =>', iYear, iMonth, iDay, iHour, iMinute, iSecond, iMillisecond);
Итак ... пока это был всего лишь пример - и выполнялось только очень простое преобразование данных (просто для примера) ... выполнение этого без карты было бы гораздо более утомительной задачей.
Конечно, это написано в версии JavaScript , что я не думаю , что слишком многие браузеры поддерживают пока (по крайней мере , полностью) , но - мы получаем там. Если бы мне нужно было запустить его в браузере, я считаю, что это было бы хорошо.
источник