2015-12-21 4 views
-2

Кажется, что замыкания заменяют использование петель в JS.В чем преимущество использования функции над циклами?

В чем преимущество передачи функции, такой как карта или уменьшение по сравнению с циклом for/while?

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) – raina77ow

+0

И если вам это не нравится, вам не нужно их использовать, большинство вещей можно сделать без новых методов (ish) Array. – 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); 
} 

Где add является function add(a, b) { return a + b; }.

Более компактный означает более читаемую и меньшую площадь поверхности для ошибок. Использование функции с именем add также повышает читаемость; мы можем легко понять, что операция состоит в том, чтобы добавить элементы массива.

В принципе, все функции массива имеют эквиваленты для цикла, которые требуют установки большего количества переменных и записи дополнительной логики. Например, это 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; 
} 

Это петли один миллион раз и возвращает массив, заполненный NaNs.В отличие от

array.map(elt => elt*2) 

работает только на одном элементе, который присутствует в положении 1000000 и возвращает разреженный массив, как хотелось бы.

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

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

Теперь я могу написать

array.map(multiply(2)) 

Этот уровень лаконичности и выразительности будет трудно для достижения в решении для петли.

forEach и map и т. Д., Вероятно, будут медленнее, чем цикл for. Это может быть проблемой, если ваш код работает миллион раз в жестком цикле. В реальном мире это редко бывает проблемой. Лучше уделять приоритетное внимание чтению и компактности кода.

Однако никто не заставляет вас использовать map или filter. В ES7 или что он будет называться, вы будете иметь возможность использовать постижения массива, чтобы сделать то же самое в еще более доступной форму:

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

, который сочетает в себе фильтр и карту.

Немного дальше, если вы планируете написать генератор, который выполняет итерацию по массиву, и дать некоторые вычисления от каждого элемента, вам понадобится использовать цикл for, поскольку нет способа получить из в пределах forEach Обратный вызов:

2

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

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

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