Как передать параметр array.map()?
Я пытаюсь отобразить значения в функцию, которая будет принимать два числа, чтобы умножаться, но у меня возникают проблемы с этим (если это не имеет смысла, взгляните на приведенные ниже примеры).
У меня есть массив чисел, и я хотел бы удвоить/утроить/четыре раза... значения этого массива. Я создал функции, которые будут делать это, и я загружаю эти double()
и triple()
в map()
.
var arr = [1, 2, 3, 4, 5];
function double(num) {
return num * 2;
}
function triple(num) {
return num * 3;
}
console.log( arr.map(double) );
console.log( arr.map(triple) );
Это решение не масштабируется, как если бы я хотел умножить значения на 5 или 10? Мне нужна более абстрактная функция, которая будет принимать параметр того, что нужно умножить. Я смущен о том, как это сделать. Моя попытка:
var arr = [1, 2, 3, 4, 5];
function multiply(num, multiplyBy) {
return num * multiplyBy;
}
console.log( arr.map(multiplyBy(4) ); // Uncaught TypeError: NaN is not a function
Как передать multiply()
параметр multiplyBy
?
Ответы
Ответ 1
Вы можете сделать что-то, называемое factory. Фактически, вы создаете функцию, которая возвращает другую функцию, которая соответствует вашим потребностям. В этом случае анонимный.
var arr = [1, 2, 3, 4, 5];
function multiplyBy(scale) {
return function(num){
return num * scale;
}
}
console.log( arr.map( multiplyBy(4) ));
Это работает, потому что область возвращаемой анонимной функции находится в пределах factory. Итак, всякий раз, когда мы создаем новую функцию, она сохранит значение scale
, которое было дано для его создания.
Изменить: Последняя часть ответа @Bergi такая же, как у меня. Понятие, по-видимому, называется каррированием. Спасибо @Bergi! Образец Factory чаще всего применяется к производству объектов, как отметил Берги, но это было единственное, что я мог подумать в то время, а javascript вроде рассматривает функции, подобные объектам. В этом конкретном случае они фактически похожи.
Ответ 2
Вы ищете частичное приложение. Например, это можно сделать с помощью bind
(или нескольких вспомогательных функций, которые поставляются с функциональными библиотеками, например в Underscore):
arr.map(multiplyBy.bind(null, 4))
однако простая функция стрелок была бы проще:
arr.map(x => multiplyBy(4, x))
Но вы также можете бесплатно получить частичное приложение, если curry ваша функция multiplyBy
, взяв множитель и вернув новый функция:
function multiplyBy(multiplier) {
return function(num) {
return num * multiplier;
};
}
// ES6 arrow functions:
const multiplyBy = multiplier => num => num * multiplier;
arr.map(multiplyBy(4));
Ответ 3
Вы можете использовать Function.prototype.bind
для создания новой функции со связанными аргументами. Например
var arr = [1, 2, 3, 4, 5];
function multiplyBy(multiplyBy, num) {
// note the "num" argument must come last if it is to represent the argument from "map"
return num * multiplyBy;
}
console.log( arr.map(multiplyBy.bind(null, 4)) ); // null is for the "this" argument