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

У меня есть массив чисел, и я хотел бы удвоить / утроить / четверть ... значения этого массива. Я создал функции, которые будут делать это, и подаю эти 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?

20
Jon 29 Авг 2017 в 03:08

3 ответа

Лучший ответ

Вы можете сделать то, что называется фабрикой. По сути, вы создаете функцию, которая будет возвращать другую функцию, адаптированную к вашим потребностям. В данном случае анонимный.

var arr = [1, 2, 3, 4, 5];

function multiplyBy(scale) {
    return function(num){
        return num * scale;
    }
}

console.log( arr.map( multiplyBy(4) ));

Это работает, потому что область действия возвращаемой анонимной функции находится в пределах фабрики. Таким образом, всякий раз, когда мы создаем новую функцию, она сохраняет значение scale, которое было задано для ее создания.

Редактировать: последняя часть ответа @ Берги такая же, как мой. Концепция, по-видимому, называется карри. Спасибо @ Берги! Как отметил Берги, шаблон «Фабрика» чаще применяется к производству объектов, но это было единственное, о чем я мог подумать в то время, и javascript вроде бы рассматривал функции как объекты. В этом конкретном случае они эффективно похожи.

21
TheCrzyMan 28 Дек 2017 в 18:54

Вы ищете частичное заявление. Это можно сделать с помощью bind < Например, / a> (или несколько вспомогательных функций, которые поставляются с функциональными библиотеками, например в Underscore):

arr.map(multiplyBy.bind(null, 4))

Однако простая функция со стрелкой будет проще:

arr.map(x => multiplyBy(4, x))

Но вы также можете получить частичную заявку бесплатно, если вы карри выполняете функцию multiplyBy, взять множитель и вернуть новую функцию:

function multiplyBy(multiplier) {
  return function(num) {
    return num * multiplier;
  };
}
// ES6 arrow functions:
const multiplyBy = multiplier => num => num * multiplier;

arr.map(multiplyBy(4));
19
Bergi 29 Авг 2017 в 07:19

Вы можете использовать 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
10
Phil 29 Авг 2017 в 00:15