Как определить карту с точки зрения ForEach

Я определил свою собственную функцию карты, которая служит той же цели, что и метод объектов Array. (Я делаю это, чтобы учиться). Код ниже.

Я хотел бы использовать метод Array forEach внутри моего собственного определения карты, но я что-то теряю концептуально. Как я смогу сделать это, используя forEach?

Работа без использования forEach

// transforming with map
// NOTE: map is already defined in JavaScript
function map(array, transformation) {
  var mapped = [];

  for (var index in array) {
    var currentElement = array[index];
    var transformedElement = transformation(currentElement);
    mapped.push(transformedElement);
  }

  return mapped;
}

Моя попытка использования forEach

function mapForEach(array, transformation) {
    var mapped = [];

    array.forEach(transformation(currentVal, index, array, mapped));

    return mapped;
}

function transformation(person, index, array, accumulator) {
    var name = person.name;

    accumulator.push(name);
}

Ответ 1

Отсутствующая концепция здесь - это пропуск по значению. Изменения в аккумуляторе не будут отражаться в forEach. forEach фактически не предназначен для возврата значения для каждой итерации. Для этого у вас есть карта.

Взято из here,

foreach выполняет итерацию по списку и применяет некоторую операцию со стороной эффекты для каждого члена списка (например, сохранение каждого из них в базу данных например)

отображает итерации по списку, преобразует каждый член этого списка и возвращает другой список того же размера с преобразованными членами (например, преобразование списка строк в верхний регистр)

Попробуйте этот код:

function mapForEach(array, transformation) {
    var mapped = array.map(transformation);
    return mapped; 
}

function transformation(person, index, array) {
    var name = person.name;
    return name; 
}

Вот JSFiddle

Если вам абсолютно необходимо использовать forEach, то вместо того, чтобы передавать значение, необходимо использовать глобальную переменную. Это было бы тогда

var accumulator =[];

function mapForEach(array, transformation) {
    array.forEach(transformation);
    return accumulator;
}

function transformation(person, index, array) {
    var name = person.name;
    accumulator.push(name);
}

JSFiddle - forEach

Ответ 2

Вы почти правы с вашим методом, но, как говорит @Katana314, вам нужно связать, а не звонить.
Вот как я это сделаю:

function map(array,mapper) {
    var ret=[];
    array.forEach((val,key)=>{
        //Since arrays are supposed to be sequential, we don't have to worry
        //about keys matching, if they don't match, the user/developer did
        //something horribly wrong.
        ret.push(mapper(val,key,array));
    });
    return ret;
}

И вот как бы я поправился.

function mapForEach(array, func) {
    var mapped = [];
    array.forEach(mapForEachPusher.bind(null,mapped,func));
    return mapped;
}
function mapForEachPusher(mapped,func,value,index,array) {
    mapped.push(func(value,index,array));
}

function extract_name(person) {
    return person.name;
}
mapForEach(
    [{name:'Billy'},{name:'Bob'},{name:'Bridget'},{name:'Brittany'},{name:'"B word"'}]
    ,extract_name
);
//["Billy", "Bob", "Bridget", "Brittany", "\"B word\""]

Это фактически то же самое, ваш способ перемещает вызов .push() из основной функции, что означает, что вам нужно передавать данные вокруг, тогда как мне нужно только ссылаться из внешней области. Единственный недостаток моего пути - накладные расходы функции, но это функция стрелки, поэтому она может сделать ее достаточно легкой, чтобы не иметь значения.