Array.prototype.map() и Array.prototype.forEach()

У меня есть массив (пример массива ниже) -

a = [{"name":"age","value":31},
     {"name":"height (inches)","value":62},
     {"name":"location","value":"Boston, MA"},
     {"name":"gender","value":"male"}];

Я хочу выполнить итерацию по этому массиву объектов и создать новый объект (не специально уменьшить).

У меня есть два подхода -

a = [{"name":"age","value":31},
     {"name":"height (inches)","value":62},
     {"name":"location","value":"Boston, MA"},
     {"name":"gender","value":"male"}];

// using Array.prototype.map()
b = a.map(function(item){
  var res = {}; 
  res[item.name] = item.value; 
  return res;
});
console.log(JSON.stringify(b));

var newObj = [];
// using Array.prototype.forEach()
a.forEach(function(d){
    var obj = {};
    obj[d.name] = d.value;
    newObj.push(obj)
});
console.log(JSON.stringify(newObj))

Ответ 1

Как вы уже говорили в комментариях, здесь нет прямого неправильного ответа. Помимо некоторых довольно тонких точек исполнения, это вопрос стиля. Задача, которую вы решаете, может быть решена с помощью цикла for, .forEach(), .reduce() или .map().

Я перечисляю их в этом порядке намеренно, потому что каждый из них может быть повторно реализован с использованием чего-либо ранее в списке. Вы можете использовать .reduce() для дублирования .map(), например, но не наоборот.

В вашем конкретном случае, если только микро-оптимизация важна для вашего домена, я бы принял решение на основе удобочитаемости и обслуживания кода. Исходя из этого, .map() делает конкретно и точно то, что вам нужно; кто-то читает ваш код, увидит его и узнает, что вы потребляете массив для создания другого массива. Вы можете выполнить это с помощью .forEach() или .reduce(), но поскольку они могут использоваться для большего количества вещей, кто-то должен принять этот дополнительный момент, чтобы понять, для чего вы их используете. .map() - это призыв, наиболее выразительный из ваших намерений.

(Да, это означает по существу приоритет эффективности понимания понимания эффективности исполнения. Если код не является частью узкого места производительности в приложении с высоким спросом, я считаю, что это подходит.)

Вы спросили о сценариях, где другим может быть предпочтительнее. В этом случае .map() работает, потому что вы выводите массив, а ваш выходной массив имеет ту же длину, что и ваш входной массив. (Опять же, что делает .map()). Если вы хотите вывести массив, но вам может потребоваться создать два (или нулевых) элемента вывода для одного элемента ввода, .map() будет отсутствовать, и я бы, вероятно, использовал .reduce(). (Chaining .filter().map() также будет возможностью для случая "пропустить некоторые входные элементы" и будет довольно разборчивым)

Если вы хотите разделить содержимое входного массива на несколько массивов вывода, вы можете сделать это с помощью .reduce() (путем инкапсуляции всех из них как свойств одного объекта), но .forEach() или for петля выглядела бы более естественной для меня.

Ответ 2

Во-первых, любой из них будет работать, и с вашим примером нет причин не использовать, что когда-либо более удобно для вашего цикла разработки. Я бы, вероятно, использовал map, так как это то, что нужно; для создания "нового массива с результатами вызова предоставленной функции для каждого элемента в этом массиве".

Однако вы спрашиваете, что является самым быстрым? Тогда ни один из них; самый быстрый на 2.5-3x будет простым для цикла (см. http://jsperf.com/loop-vs-map-vs-foreach для простого сравнения):

var newObj = [];
for (var i = 0, item; item = a[i]; i++) {
    var obj = {};
    obj[item.name] = item.value;
    newObj.push(obj);
});
console.log(JSON.stringify(newObj));