2012-03-09 14 views
16

Większość przypadków użycia metody reduce() można z łatwością przepisać za pomocą pętli for. Testowanie w JSPerf pokazuje, że funkcja reduce() jest zwykle wolniejsza o 60% -75%, w zależności od operacji wykonywanych w każdej iteracji.Czy jest jakaś realna korzyść z używania metody javascript Array reduce()?

Czy istnieje prawdziwy powód, by używać funkcji reduce(), poza możliwością pisania kodu w "stylu funkcjonalnym"? Jeśli możesz uzyskać 60% wzrost wydajności, pisząc nieco więcej kodu, dlaczego używałbyś funkcji reduce()?

EDYCJA: W rzeczywistości inne metody funkcjonalne, takie jak forEach() i map(), wszystkie wykazują podobną wydajność, będąc co najmniej 60% wolniejszą niż proste dla pętli.

Oto link do testu JSPerf (z wywołań funkcji): forloop vs forEach

Odpowiedz

5
  • Możesz chcieć scopingu. Na przykład możesz chcieć tworzyć funkcje oddzwaniania lub mieć odniesienia do obiektów javascript. Aby uzyskać więcej informacji, zobacz, dlaczego javascript nie ma zablokowanych zakresów. [edytuj: nowoczesne javascript obsługuje teraz zmienne let. Wcześniej przed ESv6, kiedy zadeklarowałeś zmienną var, została ona podniesiona tak, jakby była napisana na górze bloku kodu funkcji, więc często trzeba było pisać ciała pętli for jako funkcje. To jednak nadal obowiązuje:] Jeśli masz funkcję napisaną, możesz równie dobrze użyć stylu funkcjonalnego, chyba że jest to znaczące wąskie gardło.
  • Twój kod nie zawsze musi działać z pełną prędkością maszyny. Możesz nawet nie optymalizować kodu w wąskim gardle.
  • Dodatkowo nie podajesz "testowania na JSPerf", więc możemy je krytykować. Na przykład, jeśli masz już funkcję redukcji (lub funkcję map lub forEach), to założę się, że wydajność będzie na wartości. Nawet jeśli nie, metodologia testowania może być wadliwa, zwłaszcza biorąc pod uwagę, że wiele przeglądarek może optymalizować inaczej lub mieć różne narzuty na wywołania funkcji.

sidenote: czy jest to prawidłowy porównanie wydajności między składnią, ale porównanie nieważny wydajność w przypadku składnia nie jest pytanie pod ręką:

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

// ...versus... 

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

Byłoby to ważne porównanie wydajności:

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) 

(także w odpowiedzi na Pana EDIT: .forEach() i .map() zapewnić znacznie większą przejrzystość i uniknąć konieczności dla argumentów jawnej pętli int i=0; i<array.length; i++).

+2

Nie zgadzam się z tobą co do tego, co stanowi poprawne porównanie wyników. Pierwszym jest poprawne porównanie, ponieważ na pewno (na przykład) pytanie brzmi: "Która metoda jest najszybsza w dodawaniu jednego do każdego elementu tablicy?", A nie "Która metoda jest najszybsza, ale jakakolwiek metoda nie używająca funkcji jest zdyskwalifikowana z wpisu ". Zgadzam się, że jeśli założysz, że chcesz mieć jakąś funkcję do celów ustalania zakresu/zamknięcia, to równie dobrze możesz użyć '.reduce()' lub '.forEach()' lub cokolwiek innego. – nnnnnn

+0

Pytanie dotyczy dokładnie składni, więc jest to poprawne porównanie wydajności. Być może powinienem przeformułować pytanie w scenariuszu, w którym chcesz wycisnąć każdy możliwy kawałek wydajności. W takim przypadku nie mogę znaleźć dobrego powodu, aby nie używać zwykłej pętli for. Czy możesz podać konkretny przykład, w którym konieczne jest ustalenie zakresu? –

+0

@EvanYou: '[1,2,3].forEach (function (x) {setTimeout (function() {alert (x)}, 1000)}) '(alert 1,2,3) versus' for (var i = 0; i <4; i ++) {setTimeout (function() {alert (i)}, 1000)} '(alerty 4,4,4) – ninjagecko

Powiązane problemy