2015-12-21 48 views
-2

似乎閉包正在取代JS中循環的使用。在循環中使用函數的優點是什麼?

與for/while循環相比,傳遞函數(如map或reduce)的優點是什麼?

var numbers = [1, 4, 9]; 
var doubles = numbers.map(function(num) { 
    return num * 2; 
}); 

var doubles = []; 
for (i = 0; i < numbers.length; i++) { 
    doubles[i] = numbers[i] * 2; 
} 
+4

呃,這不是關閉,這是什麼方法呢? 'map'和'reduce'對數組做了特定的事情,它們不僅僅像'for'循環那樣迭代? – adeneo

+1

簡潔性(使用es6中的箭頭funcs會更好) – raina77ow

+0

如果您不喜歡它們,則不必使用它們,但大多數情況下都可以在不使用新的(ish)數組方法的情況下完成。 – adeneo

回答

3

我不知道爲什麼你會打電話給使用map的「閉包」。閉包完全是另一回事。 map是一個高階函數 - 定義爲一個函數,它對(函數或函數)進行操作。這種編程風格可以鬆散地稱爲「功能性」。

使用map等功能有其優點和缺點。正如一位評論者指出的那樣,這是更緊湊:

function sum(array) { 
    var sum = 0; 
    for (var i = 0; i < array.length; i++) sum += array[i]; 
    return sum; 
} 

function sum(array) { 
    return array.reduce(add); 
} 

哪裏addfunction add(a, b) { return a + b; }

更緊湊意味着更易讀和更少的表面區域的bug。使用名爲add的功能也增強了可讀性;我們可以很容易地認爲操作是添加數組的元素。

基本上,所有的數組函數都有for循環等價物,它們需要設置更多的變量和編寫更多的邏輯。例如,map

function map(array, fn) { 
    var result = []; 
    for (var i = 0; i < array.length; i++) result.push(fn(array[i])); 
    return result; 
} 

這可以寫成(多)更簡潔的array.map(fn)

在很多情況下,我們可能已經定義了函數來進行元素映射或者我們想要做的元素過濾。在這種情況下,我們可以簡單地使用map,reduce等的功能。

map和它的朋友也有優點,他們對稀疏數組很友善。例如:

var a = []; 
a[1000000] = 1; 

現在我們加倍的每個元素:

function double(array) { 
    var result = []; 
    for (var i = 0; i < array.length; i++) result.push(array[i] * 2); 
    return result; 
} 

這個循環一百萬次,並返回充滿NaN的數組。相比之下

array.map(elt => elt*2) 

僅是存在於百萬位置,並返回一個稀疏陣列作爲一個希望單個元件上進行操作。

功能風格也爲靈活性打開了額外的可能性。假設我們想概括一下乘法事物的概念。我可以寫一個高階函數來創建它通過特定的因素乘以某個值的函數:

function multiply(n) { 
    return function(x) { 
    return n * x; 
    }; 
} 

現在我可以寫

array.map(multiply(2)) 

簡潔和表現的這種水平將是硬在for-loop解決方案中實現。

forEach and map等可能比for循環慢。如果您的代碼在緊密循環中運行一百萬次,這可能是一個問題。在現實世界中,它很少是一個問題。優先考慮代碼可讀性和緊湊性。

但是,沒有人強迫您使用mapfilter。在ES7或不管它會叫,你將能夠使用數組解析來實現在更可讀的方式同樣的事情:

[ for (i of array) if (i % 2) i + 1 ] 

它結合了過濾器和地圖。

更遠一點,如果你打算寫一個遍歷數組的生成器,並且從每個元素產生一些計算,你將需要使用for循環,因爲沒有辦法從在forEach回調:

function *double(array) { 
    for (var i = 0; i < array.length; i++) yield array[i]*2; 
} 

function *double(array) { 
    array.forEach(elt => yield elt*2); // DOESN'T WORK!! 
} 
2

這是一個範式轉變。後者是一種命令性編程形式,其中用戶是創建計算機消耗的數據的人。前者基本上是一種更加基於功能的方法,源於數學,利用已經存在的數據(代碼)。

雖然應用於計算機的當前狀態,但理論(處理)優勢並不存在,但隨着處理能力的增強,功能編程變得更加有用。

函數式編程允許基於數學的推理形式強調輸入和輸出。由於功能是一流的數據類型,JavaScript特別擅長處理這種風格。

相關問題