2012-03-09 1 views
16

Большинство примеров использования метода reduce() можно легко переписать с помощью цикла for. И тестирование на JSPerf показывает, что reduce() обычно на 60% -75% медленнее, в зависимости от операций, выполняемых внутри каждой итерации.Есть ли какая-либо реальная польза для использования метода javascript Array reduce()?

Есть ли настоящая причина использовать reduce(), а не возможность писать код в «функциональном стиле»? Если вы можете получить прирост производительности на 60%, написав еще немного кода, зачем вам когда-либо использовать reduce()?

EDIT: Фактически, другие функциональные методы, такие как forEach() и map(), показывают аналогичную производительность, будучи как минимум на 60% медленнее, чем простые для циклов.

Вот ссылка на тест JSPerf (с вызовами функции): forloop vs forEach

ответ

5
  • Вы можете область видимости. Например, вы можете использовать функции обратного вызова или ссылаться на объекты javascript. Для получения дополнительной информации см., Почему javascript не заблокирован. [edit: современный javascript теперь поддерживает let переменных. Назад до ESv6, когда вы объявили переменную var, она поднялась, как если бы она была написана в верхней части функционального кода, поэтому вам часто приходилось писать тела функций for-loops в качестве функций. Это все еще применяется, если:] Если у вас была написанная функция, она может также использовать функциональный стиль, если это не является значительным узким местом.
  • Ваш код не всегда должен работать на полной скорости машины. Вы даже не можете оптимизировать код в узком месте.
  • Кроме того, вы не предоставляете свое «тестирование на JSPerf», чтобы мы могли его критиковать. Например, если у вас уже есть функция сокращения (или функция map или forEach), то я уверен, что производительность будет на уровне. Даже если это не так, методология тестирования может быть ошибочной, особенно учитывая, что многие браузеры могут оптимизировать по-другому или иметь разные служебные служебные вызовы.

Sidenote: это корректное сравнение производительности между синтаксисом, но сравнение недействителен производительность в том, когда синтаксис не вопрос под рукой:

myArray.map(function(x){return x+1}) 

// ...versus... 

for(var i=0; i<myArray.length; i++) { 
    myArray[i] = myArray[i]+1; 
} 

Это было бы допустимым сравнение производительности:

myArray.forEach(function(x){return x+1}) 

// ...versus... 

var plusOne = function(x){return x+1}; 
for(var i=0; i<myArray.length; i++) { 
    plusOne(myArray[i]); 
} 

// (may need a side-effect if the compiler is smart enough to optimize this) 

(Кроме того, в ответ на ваши изменения: .forEach() и .map() обеспечивают гораздо больше ясности, и избежать необходимости для явного цикла int i=0; i<array.length; i++ аргументы.)

+2

Я не согласен с вами в отношении того, что составляет допустимое сравнение производительности. Параметр _first_ является допустимым сравнением, потому что, безусловно, (для вашего примера) возникает вопрос: «Какой метод наиболее быстрый при добавлении одного к каждому элементу массива?», А не «Какой метод выполняется быстрее, но любой метод, не использующий вызов функции, дисквалифицирован от входа ". Я согласен с тем, что если вы предполагаете, что хотите использовать функцию в любом случае для целей определения области охвата/закрытия, вы также можете использовать '.reduce()' или '.forEach()' или что-то еще. – nnnnnn

+0

Вопрос в том, что касается синтаксиса, поэтому это допустимое сравнение производительности. Возможно, я должен перефразировать вопрос в сценарии, где вы хотите сжать все возможные бит производительности. В этом случае я не могу найти оснований не использовать простой цикл. Можете ли вы привести конкретный пример, в котором необходимо определить область охвата? –

+0

@EvanYou: '[1,2,3].forEach (function (x) {setTimeout (function() {alert (x)}, 1000)}) '(предупреждения 1,2,3) по сравнению с' for (var i = 0; i <4; i ++) {setTimeout (function() {alert (i)}, 1000)} '(предупреждения 4,4,4) – ninjagecko