В чем разница между подчеркиванием _.each и _.map?
Я использую UnderscoreJs. Рассмотрим этот код:
var docs = [
{name : 'Anders', niche : 'Web Development'},
{name : 'Johnny', niche : 'Design'},
{name : 'Eric', niche : 'PhotoShop'}
];
var newDocs = _.map(docs, function (doc){
delete doc.niche;
return doc;
});
Не имеет значения, использую ли я здесь .each
или .map
. Результат точно такой же.
На самом деле разница между двумя в приведенном выше случае?
Ответы
Ответ 1
map
предназначен для функционального метода сопоставления: его аргумент функции должен возвращать значение, но не ожидается каких-либо побочных эффектов.
each
является просто функциональной заменой императивного цикла for
: его цель состоит в том, чтобы иметь эффект, и он не должен возвращать какое-либо значение.
Например, это было бы более подходящим для map
:
var docs = getDocs();
var docTitles = _.map(docs, function (doc){
return doc.title;
});
// expect `docs` to be unchanged
В то время как это было бы подходящим использованием для each
:
var docs = getDocs();
_.each(docs, function (doc){
delete doc.niche;
});
// expect `docs` to be altered.
Ответ 2
_. each (list, iteratee)
Итерации над списком элементов, каждый из которых приводит к итерационной функции.
Каждый вызов iteratee вызывается с тремя аргументами: (element, index, list). Если список является объектом JavaScript, аргументы iteratee будут (значение, ключ, список). Возвращает список цепочки.
_.each({one: 1, two: 2, three: 3}, alert);
=> alerts each number value in turn...
_. map (list, iteratee)
Создает новый массив значений, отображая каждое значение в списке через функцию преобразования (iteratee).
Если список является объектом JavaScript, аргументы iteratee будут (значение, ключ, список).
_.map({one: 1, two: 2, three: 3}, function(num, key){ return num * 3; });
=> [3, 6, 9]
см. документация
Ответ 3
Вы можете просто посмотреть исходный код, чтобы увидеть разницу:
-
_.each
:
_.each = _.forEach = function(obj, iteratee, context) {
if (obj == null) return obj;
iteratee = createCallback(iteratee, context);
var i, length = obj.length;
if (length === +length) {
for (i = 0; i < length; i++) {
iteratee(obj[i], i, obj);
}
} else {
var keys = _.keys(obj);
for (i = 0, length = keys.length; i < length; i++) {
iteratee(obj[keys[i]], keys[i], obj);
}
}
return obj;
};
-
_.map
:
_.map = _.collect = function(obj, iteratee, context) {
if (obj == null) return [];
iteratee = _.iteratee(iteratee, context);
var keys = obj.length !== +obj.length && _.keys(obj),
length = (keys || obj).length,
results = Array(length),
currentKey;
for (var index = 0; index < length; index++) {
currentKey = keys ? keys[index] : index;
results[index] = iteratee(obj[currentKey], currentKey, obj);
}
return results;
};
Ответ 4
Ваше утверждение о том, что результаты "точно такие же", неверно. Функция _.each()
возвращает исходный список, но _.map()
возвращает новый список. Вы сами изменяете исходные объекты по ходу, поэтому вы получаете ссылки на одни и те же объекты в каждом списке, но с _.map()
вы получаете два отдельных экземпляра массива.