2017-08-29 34 views
15

我試圖將值映射到一個函數,該函數將接受兩個數字相乘,但這樣做有困難(如果這沒有意義,請看下面的示例)。如何將參數傳遞給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參數?

回答

16

你可以做一些叫做工廠的東西。實際上,您將創建一個函數,以返回另一個適合您需求的函數。在這種情況下,一個匿名的。

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

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

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

這是可行的,因爲返回的匿名函數的範圍在工廠的範圍之內。所以,當我們產生一個新的功能時,它將保留爲其生產而給出的值scale

編輯:@Bergi的答案的最後部分與我的一樣。這個概念顯然被稱爲咖喱。謝謝@Bergi!正如Bergi指出的那樣,工廠模式更常用於對象的生成,但它是我當時唯一能想到的東西,而javascript類似於對象的對待功能。在這個特定的情況下,它們實際上是相似的。

+3

我只會對返回對象的函數使用術語「工廠」。 – Bergi

+0

我讓我的答案更具可讀性,我使用奇怪的縮進只是將ES6箭頭函數轉換爲單行更明顯。 – Bergi

+1

這個答案比使用'.bind'更容易理解 – Denny

10

您可以使用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

14

您正在尋找partial application。它可以與bind例如進行(或數量的輔助函數來與功能的庫,例如in 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));