JavaScript에서 배열을 반복하는 가장 빠른 방법은 무엇입니까?


249

나는 당신이 다음과 같이 루프를 작성해야한다는 책에서 배웠습니다.

for(var i=0, len=arr.length; i < len; i++){
    // blah blah
}

그래서 arr.length매번 계산되지 않습니다.

다른 사람들은 컴파일러가 이것에 대해 약간의 최적화를 할 것이라고 말합니다.

for(var i=0; i < arr.length; i++){
    // blah blah
}

실제로 어떤 방법이 가장 좋은지 알고 싶습니다.


1
: 또한 가치 모양 배열 루프를 처리 할 때 jsperf.com/array-loop-var-caching
cloakedninjas

@ wong2 Tthis 벤치 마크 에서 Browserdiet는 대안의보다 완전한 컬렉션이 있습니다.
도미


이전 jsben에서 개선되었습니다 : jsben.ch/#/R6LbS
Corbfon

for ... of이 경쟁에 대한 루프를 소개 할 ​​수 있습니까 ? 구문은 캐싱없이 for 루프보다 훨씬 쉬운 것처럼 보이며 for 루프 사용으로 전환 해야하는지 알고 싶습니다.
프로그래머

답변:


339

대부분의 최신 브라우저에서이 테스트를 수행 한 후 ...

http://jsben.ch/dyM52

현재 가장 빠른 형태의 루프 (그리고 내 의견으로는 가장 문법적으로 명백합니다).

길이 캐싱이있는 루프의 표준

for (var i = 0, len = myArray.length; i < len; i++) {

}

나는 이것이 JavaScript 엔진 개발자들에게 박수를 보내는 경우라고 분명히 말할 것입니다. 런 시간에 최적화되어야한다 명확성 , 하지 영리함 .


6
흥미롭게도, IE9에서이 빠르다 : 대한 (var에 내가 0, 렌 = myArray.length를 = 나는 <렌 ++ I) {} // 접두사 증분 대신 후위의
크리스토퍼 Bennage

4
다른 이유로 사용하려면 접두사보다 접두사 연산자 선호를 참조하십시오 ++i.
Bennett McElwee

4
@BennettMcElwee 제안으로 나는 접두사 연산자를 사용하여 테스트가 좀 더 빠르게 실행 : for(var i=0, len=myArray.length; i<len; ++i) 확인 jsperf.com/caching-array-length/84
victmo

21
이 루프를 조심해서 사용해야합니다. 나는 그것을 사용하기 시작했고 한 가지 실수로 버그를 추적하기가 어려웠습니다. : 당신이 둥지 같은 두 개의 루프의 경우 jsfiddle.net/KQwmL/1을 . 두 루프에서 var len의 이름을 다르게 지정해야합니다. 그렇지 않으면 두 번째 루프가 첫 번째 len을 덮어 씁니다.
Rui Marques

6
@WillshawMedia 단일 var문으로 여러 변수를 선언 할 수 있습니다 . 작성 방법 len은 실제로 제안한 범위입니다.
jondavidjohn

90

자바 스크립트 배열을 반복하는 가장 빠른 방법은 다음과 같습니다.

var len = arr.length;
while (len--) {
    // blah blah
}

전체 비교는 http://blogs.oracle.com/greimer/entry/best_way_to_code_a 를 참조하십시오


1
사용하는 것을 잊지 마십시오 var(그렇지 않으면 len전역 변수가 됨). 루프 벤치 마크에 대한 자세한 내용은 jsperf.com/loops 를 참조하십시오 .
Mathias Bynens

22
이 답변에 기반을 둔 블로그 게시물은 거의 4 세가되었으며 그 당시 js 엔진에서 많은 변화가있었습니다. 업데이트 된 비교는 아래 답변을 참조하십시오.
jondavidjohn

1
@jondavidjohn에 동의합니다. 이 코드를 테스트 한 결과 효율성이 떨어졌습니다 ... jsperf.com/caching-array-length/84
victmo

위의 대답은 for 루프보다 훨씬 보편적으로 (브라우저에서) 거의 느립니다. 허용 된 답변의 JSPerf 링크를 참조하십시오. 그것은 수치스러워서 읽기 쉬운 IMO이기 때문입니다.
Letharion

3
@ jondavidjohn이 '내 답변 아래'라는 의미는 '내 답변 위'라는 것을 추측합니다.
Shanimal

40

2016 년 6 월 현재 최신 Chrome에서 일부 테스트 (2016 년 5 월 브라우저 시장의 71 % 이상 증가) :

  • 가장 빠른 루프는 캐싱 길이의 유무에 관계없이 거의 비슷한 성능을 제공 하는 for 루프 입니다. 캐시 된 길이를 가진 for 루프는 캐싱없는 것보다 더 나은 결과를 제공하기도하지만 그 차이는 거의 무시할 수 있습니다. 즉, 엔진이 이미 표준을 선호하도록 최적화되어 있으며 아마도 캐싱없는 루프에 대해 가장 간단한 방법 일 것입니다.
  • 감소 된 while 루프는 for 루프보다 약 1.5 배 느 렸습니다.
  • 콜백 함수 (표준 forEach와 같은)를 사용하는 루프는 for 루프보다 약 10 배 느 렸습니다.

나는이 스레드가 너무 오래되었다고 생각하고 프로그래머가 길이를 캐싱하거나 더 나은 성능을 달성하기 위해 감소와 함께 리버스 트래버스를 사용해야한다고 생각하는 오해의 소지가 있습니다. 간단하고 간단한 for 루프보다 읽기 쉽고 오류가 발생하기 쉬운 코드를 작성하십시오. 따라서 다음을 권장합니다.

  • 앱이 많은 항목을 반복하거나 루프 코드가 자주 사용되는 함수 내에 있으면 간단한 for 루프가 답입니다.

    for (var i = 0; i < arr.length; i++) {
      // Do stuff with arr[i] or i
    }
  • 앱이 많은 항목을 실제로 반복하지 않거나 여기저기서 작은 반복을 수행 해야하는 경우 표준 forEach 콜백 또는 선택한 JS 라이브러리의 유사한 함수를 사용하면 이해하기 쉽고 오류가 덜 발생할 수 있습니다. 인덱스 변수 범위가 닫히고 대괄호를 사용하지 않고 배열 값에 직접 액세스 할 수 있습니다.

    arr.forEach(function(value, index) {
      // Do stuff with value or index
    });
  • 수십억 행을 반복하는 동안 몇 밀리 초를 긁어 내야하며 배열의 길이가 프로세스를 통해 변경되지 않으면 for 루프에서 길이를 캐싱하는 것을 고려할 수 있습니다. 요즘에는 이것이 실제로 필요하지 않다고 생각합니다.

    for (var i = 0, len = arr.length; i < len; i++) {
      // Do stuff with arr[i]
    }

아니. jsbench.github.io/#67b13d4e78cdd0d7a7346410d5becf12 는 가장 빠른 것이 "역 루프, 암시 적 비교, 인라인 코드"(105,221 ops / sec) 인 반면 "루프, 캐시 된 값, 인라인 코드"는 76,635 ops / sec (크롬 38.0.2125.111) 인 것으로 나타났습니다. )
Fr0sT

@ Fr0sT 벤치 마크는 인덱스 1에서 <= 길이까지 배열을 순회하는 다른 시나리오입니다. 물론 이것은 다른 결과로 이어질 것입니다. <length 인 제로 기반 배열을 탐색하려고 시도하면 일반적인 시나리오입니다. 일반적인 "for"루프를 사용하면 결과가 더 잘 최적화됩니다 (캐시 길이가 약간 빠름).
CGodo

Kyopaxa는 벤치 마크를 (0 <= i <길이)로 변경했으며 결과는 동일합니다. "역 루프, 암시 적 비교, 함수 호출"은 365kops / sec를 기록한 반면 "루프, 캐시 된 값, 인라인 코드"는 350kops / sec를 기록 (FF 51)
Fr0sT

@ Fr0sT 0과 같은 캐시 된 for-loop를 같은 비교없이 바꾸면 for(let i=0, j=array.length; i < j; i++)순방향 for 루프는 상당히 빨라집니다. 몇 가지 테스트에서 내가 이겼습니다. 대부분의 오류 범위 또는 역 루프 내에있었습니다.
Isaac B

1
@IsaacB와 모두, 죄송합니다. 벤치가 상당히 부정확하다는 것을 알지 못했습니다. 모든 직접 루프는 1..length를 반복하지만 역 루프는 길이를 반복합니다 ..0 (arr [length] 항목이 유효하지 않습니다). 테스트를 수정 한 결과 "루프, 인라인 코드"360,616 ops / sec ± 0.27 %, "루프, 캐시 된 값, 인라인 코드"345,786 ops / sec ± 2.18 % (Sic!) "Reverse loop, 암시 적 비교, 인라인 코드 "322,640 ops / sec ± 2.90 % (!!!). 테스트는 FF51에 의해 실행되었습니다. 새 벤치는 여기 jsbench.github.io/#6bdfcd2692ba80c16a68c88554281570 입니다. 따라서 루프를 어지럽히는 것은 의미가없는 것 같습니다.
Fr0sT

31

순서가 중요하지 않은 경우이 스타일을 선호합니다.

for(var i = array.length; i--; )

길이를 캐시하고 쓰기가 훨씬 짧습니다. 그러나 배열을 역순으로 반복합니다.


6
방금 죽였어
Vignesh Raja

i> = 0;이 필요하지 않습니까?
MarwaAhmad

3
@MarwaAhmad : 아니요 i--. 숫자를 반환하며 일단 숫자가 0조건 false이기 때문 Boolean(0) === false입니다.
Felix Kling

31

2018 년에 업데이트가 좋을 수 있습니다 ...

그리고 나는 정말로 받아 들여진 대답동의하지 않아야한다 . 다른 브라우저에서 지연됩니다. 일부 할 forEach몇 가지가 빠르고 for-loop, 일부 while 여기에 모든 방법에 대한 벤치 마크입니다 http://jsben.ch/mW36e

arr.forEach( a => {
  // ...
}

당신이 많이 위해 루프 등을 볼 수 있기 때문에 그리고 for(a = 0; ... )없이 'var에'변수는 전 세계적으로 정의 될 것이라고 언급하는 다음의 가치 및이 수는 느린거야, 그래서 극적으로 속도에 영향을 미칩니다.

더프의 장치는 오페라에서 더 빠르게 실행되지만 파이어 폭스에서는 그렇지 않습니다

var arr = arr = new Array(11111111).fill(255);
var benches =     
[ [ "empty", () => {
  for(var a = 0, l = arr.length; a < l; a++);
}]
, ["for-loop", () => {
  for(var a = 0, l = arr.length; a < l; ++a)
    var b = arr[a] + 1;
}]
, ["for-loop++", () => {
  for(var a = 0, l = arr.length; a < l; a++)
    var b = arr[a] + 1;
}]
, ["for-loop - arr.length", () => {
  for(var a = 0; a < arr.length; ++a )
    var b = arr[a] + 1;
}]
, ["reverse for-loop", () => {
  for(var a = arr.length - 1; a >= 0; --a )
    var b = arr[a] + 1;
}]
,["while-loop", () => {
  var a = 0, l = arr.length;
  while( a < l ) {
    var b = arr[a] + 1;
    ++a;
  }
}]
, ["reverse-do-while-loop", () => {
  var a = arr.length - 1; // CAREFUL
  do {
    var b = arr[a] + 1;
  } while(a--);   
}]
, ["forEach", () => {
  arr.forEach( a => {
    var b = a + 1;
  });
}]
, ["for const..in (only 3.3%)", () => {
  var ar = arr.slice(0,arr.length/33);
  for( const a in ar ) {
    var b = a + 1;
  }
}]
, ["for let..in (only 3.3%)", () => {
  var ar = arr.slice(0,arr.length/33);
  for( let a in ar ) {
    var b = a + 1;
  }
}]
, ["for var..in (only 3.3%)", () => {
  var ar = arr.slice(0,arr.length/33);
  for( var a in ar ) {
    var b = a + 1;
  }
}]
, ["Duff's device", () => {
  var len = arr.length;
  var i, n = len % 8 - 1;

  if (n > 0) {
    do {
      var b = arr[len-n] + 1;
    } while (--n); // n must be greater than 0 here
  }
  n = (len * 0.125) ^ 0;
  if (n > 0) { 
    do {
      i = --n <<3;
      var b = arr[i] + 1;
      var c = arr[i+1] + 1;
      var d = arr[i+2] + 1;
      var e = arr[i+3] + 1;
      var f = arr[i+4] + 1;
      var g = arr[i+5] + 1;
      var h = arr[i+6] + 1;
      var k = arr[i+7] + 1;
    }
    while (n); // n must be greater than 0 here also
  }
}]];
function bench(title, f) {
  var t0 = performance.now();
  var res = f();
  return performance.now() - t0; // console.log(`${title} took ${t1-t0} msec`);
}
var globalVarTime = bench( "for-loop without 'var'", () => {
  // Here if you forget to put 'var' so variables'll be global
  for(a = 0, l = arr.length; a < l; ++a)
     var b = arr[a] + 1;
});
var times = benches.map( function(a) {
                      arr = new Array(11111111).fill(255);
                      return [a[0], bench(...a)]
                     }).sort( (a,b) => a[1]-b[1] );
var max = times[times.length-1][1];
times = times.map( a => {a[2] = (a[1]/max)*100; return a; } );
var template = (title, time, n) =>
  `<div>` +
    `<span>${title} &nbsp;</span>` +
    `<span style="width:${3+n/2}%">&nbsp;${Number(time.toFixed(3))}msec</span>` +
  `</div>`;

var strRes = times.map( t => template(...t) ).join("\n") + 
            `<br><br>for-loop without 'var' ${globalVarTime} msec.`;
var $container = document.getElementById("container");
$container.innerHTML = strRes;
body { color:#fff; background:#333; font-family:helvetica; }
body > div > div {  clear:both   }
body > div > div > span {
  float:left;
  width:43%;
  margin:3px 0;
  text-align:right;
}
body > div > div > span:nth-child(2) {
  text-align:left;
  background:darkorange;
  animation:showup .37s .111s;
  -webkit-animation:showup .37s .111s;
}
@keyframes showup { from { width:0; } }
@-webkit-keyframes showup { from { width:0; } }
<div id="container"> </div>


3
@ Maykonn 당신은 아마 "그리고 그것은 오페라 미니 이외의 모든 곳에서 작동합니다"라고 말하고 싶었다
dube

3
@Maykonn 모든 사용자의 0.18 %에 IE8이 있기 때문에 기본보기에 표시되지 않으며이를 지원하는 데 시간을 낭비해서는 안됩니다. 2018 년에 그것은 죽은 말입니다.
dube

1
전 세계의 모든 사용자를 고려하는 것이 사실입니다. 그러나 불행히도 세계의 특정 부분에서 IE8은 아직 관련이 있습니다.
Maykonn

1
다른 브라우저에서는 다른 방법으로 다른 결과를 얻을뿐만 아니라 동일한 브라우저에서 다른 입력으로 다른 결과를 얻을 수 있습니다. 거대한 숫자 전용 배열은 매우 최적화되지만 작은 혼합 배열은 최적화되지 않습니다.
Kaiido

1
@Tahlil 감사합니다.
nullqube 2016 년

19

2014 년 While이 돌아왔다

논리적으로 생각하십시오.

이거 봐요

for( var index = 0 , length = array.length ; index < length ; index++ ) {

 //do stuff

}
  1. 최소 2 개의 변수 (인덱스, 길이)를 만들어야합니다
  2. 색인이 길이보다 작은 지 확인해야합니다.
  3. 인덱스를 늘려야 함
  4. for루프는 3 개 개의 매개 변수를 가지고

이제 왜 이것이 더 빠를까요?

var length = array.length;

while( --length ) { //or length--

 //do stuff

}
  1. 하나의 변수
  2. 수표 없음
  3. 지수가 감소합니다 (기계는 선호합니다)
  4. while 하나의 매개 변수 만 있음

Chrome 28에서 for 루프가 while보다 빠르다는 것을 알았을 때 나는 완전히 혼란 스러웠습니다. 이것은 일종의 벤이 있어야합니다

"어, 모두가 for 루프를 사용하고 있습니다. 크롬을 개발할 때 이것에 초점을 맞추겠습니다."

그러나 이제 2014 년에 while 루프가 크롬으로 돌아 왔습니다. 2 배 더 빠르며, 다른 / 구형 브라우저에서는 항상 빠릅니다.

최근에 몇 가지 새로운 테스트를했습니다. 실제 환경에서 짧은 코드는 가치가 없으며 jsperf는 실제로 while 루프를 제대로 실행할 수 없습니다. 시간이 걸리는 array.length를 다시 만들어야하기 때문입니다.

jsperf에서 while 루프의 실제 속도를 얻을 수 없습니다.

당신은 당신의 자신의 사용자 정의 함수를 생성하고 확인해야 window.performance.now()

그리고 그래 ... while 루프가 더 빠를 방법은 없습니다.

실제 문제는 실제로 dom 조작 / 렌더링 시간 / 드로잉 시간 또는 호출하고 싶습니다.

예를 들어 좌표와 충돌을 계산 해야하는 캔버스 장면이 있습니다 ... 10-200 MicroSeconds (밀리 초가 아닌) 사이에 수행됩니다. 실제로 모든 것을 렌더링하는 데 몇 밀리 초가 걸립니다. DOM에서와 동일합니다.

그러나

loop경우에 따라 for 를 사용하는 또 다른 수퍼 퍼포먼스 방법이 있습니다 ... 예 : 배열 복사 / 복제

for(
 var i = array.length ;
 i > 0 ;
 arrayCopy[ --i ] = array[ i ] // doing stuff
);

매개 변수 설정을 확인하십시오.

  1. while 루프와 동일하지만 하나의 변수 만 사용하고 있습니다.
  2. 인덱스가 0보다 큰지 확인해야합니다.
  3. 보시다시피,이 접근법은 모든 사람들이 사용하는 표준 for 루프와 다릅니다 .3 번째 매개 변수 내부에서 작업을 수행하고 배열 내부에서 직접 감소합니다.

말했다, 이것은 확인 같은 기계-

나는 그것을 조금 더 짧게 만들고 쓸모없는 것들을 제거하고 같은 스타일을 사용하여 이것을 썼다고 생각했습니다.

for(
 var i = array.length ;
 i-- ;
 arrayCopy[ i ] = array[ i ] // doing stuff
);

짧아도 i한 번 더 사용 하면 모든 속도가 느려집니다. 이전 for루프와 루프 보다 1/5 느립니다 while.

참고 :;없이 looo의 후 매우 중요하다{}

방금 jsperf가 스크립트를 테스트하는 가장 좋은 방법은 아니라고 말했더라도 .. 여기에 2 개의 루프가 추가되었습니다.

http://jsperf.com/caching-array-length/40

그리고 여기 자바 스크립트의 성능에 대한 또 다른 대답이 있습니다.

https://stackoverflow.com/a/21353032/2450730

이 답변은 자바 스크립트 작성 방법을 보여줍니다. 당신이 그것을 읽을 수 없다면, 당신은 자바 스크립트에 대한 답변을 얻거나 책을 읽습니다 http://www.ecma-international.org/ecma-262/5.1/


이 대답은 아주 좋은 것으로 시작됩니다 . 나는 지난 몇 년 동안 이보다 for빠르다는 것을 알았 습니다 while. 그리고 한 번 crome-dev에서 읽은 이유는 당신이 언급 한 이유 때문입니다. while다시 잡기 전에 시간 문제가 될 것입니다. 그 시점부터 답변의 첫 부분에있는 논리 가 유지됩니다 (다시 한 번, 예). 그러나 최신 구현은 더 이상 모든 ecma 지정 단계를 따르지 않습니다 (최적화). 이제 엔진이 더 이상 가장 눈에 띄지 않는 병목 현상이 아니기 때문에 이제 리버스 루프에서 CPU 캐시 누락을 실제로 확인할 수 있습니다 !
GitaarLAB

설명을 듣고 답을 바로 잡거나 새로운 것을 배울 수 있습니다. btw 대답은 이제 1 년 이상되었습니다 ... 브라우저는 항상 그렇듯이 시간이 지남에 따라 변경되었을 수 있습니다 ...
cocco

내 의견으로는, while (--length)은 0이 거짓이기 때문에 기술적으로 효과가 있기 때문에 악의적입니다.
scott.korin

네 ... 지금은 오래된 글입니다 ...하지만 나는 단순함을 좋아합니다. 그리고 두 경우 모두에 대해 언급했듯이 무엇을 작성해야하는지 알아야합니다. 다른 쪽에서 나는 여물통 음수를 반복 할 필요가 없었습니다.
cocco

9
"기계는 이것을 선호한다"
CocoaBean

11

http://jsperf.com/caching-array-length/60

내가 준비한 (오래된 것을 재사용함으로써) 테스트의 최신 개정판이 한 가지를 보여줍니다.

캐싱 길이는 그다지 중요하지 않지만 해를 끼치 지 않습니다.

위에서 새로 링크 된 탭에서 테스트를 처음 실행할 때마다 데비안 스퀴즈 64 비트 ( 데스크탑 하드웨어 )의 Chrome, Opera 및 Firefox에서 마지막 4 개의 스 니펫 (차트에서 3, 5, 7 및 10 번째 차트)에 대한 최상의 결과를 얻습니다. ). 후속 실행은 상당히 다른 결과를 제공합니다.

성능 측면의 결론은 간단합니다.

  • for 루프 (앞으로)로 이동하고 !==대신을 사용하여 테스트하십시오 <.
  • 나중에 배열을 다시 사용할 필요가 없으면 shift()줄어든 길이의 루프와 파괴적인 배열의 while 루프 도 효율적입니다.

tl; dr

현재 아래 패턴 (2011.10)이 가장 빠른 것으로 보입니다.

for (var i = 0, len = arr.length; i !== len; i++) {
    ...
}

arr.length여기서 캐싱 은 중요하지 않으므로 테스트 만하면 i !== arr.length성능이 떨어지지 않지만 코드가 짧아집니다.


추신 : 나는 shift()그 결과가있는 스 니펫에서 0 번째 요소에 액세스하는 대신 사용할 수 있다는 것을 알고 있지만 이전 개정을 재사용 한 후 (루프가 잘못 되었음) 나중에 간과하고 이미 얻은 결과를 잃고 싶지는 않았습니다.


let current = arr [i]와 같은 루프를 변수 내부에서 작성하면 성능 (큰 메모리 할당)을 줄일 수 있습니까? 아니면 루프 전에 전류를 선언하는 것이 더 좋을까요? 아니면 루프 내부의 모든 장소에서 arr [i]를 사용합니까?
Makarov Sergey

8

순수한 성능처럼 "최고"? 또는 성능 가독성?

순수한 성능 "최고"는 캐시와 ++ 접두사 연산자를 사용하는 것입니다 (내 데이터 : http://jsperf.com/caching-array-length/189 )

for (var i = 0, len = myArray.length; i < len; ++i) {
  // blah blah
}

캐시없는 for-loop는 실행 시간과 프로그래머 읽기 시간의 균형이 가장 좋다고 주장합니다. C / C ++ / Java로 시작한 모든 프로그래머는 이것을 읽어야하는 ms를 낭비하지 않습니다.

for(var i=0; i < arr.length; i++){
  // blah blah
}

2
가독성 +1 len이름이 아무리 잘 지정 되더라도 항상 첫 번째 루프에서 이중 테이크를 수행해야합니다. 두 번째 루프의 의도는 분명합니다.
Josh Johnson

7

** 루프 내부의 배열 길이를 캐시하면 몇 초의 시간이 생략됩니다. 배열에 더 많은 항목이있는 경우 배열의 항목에 따라 시간의 양과 관련하여 큰 차이가 있습니다 *

**

sArr; //Array[158];

for(var i = 0 ; i <sArr.length ; i++) {
 callArray(sArr[i]); //function call
}

***end: 6.875ms***

**

**

sArr; //Array[158];
for(var i = 0,len = sArr.length ; i < len ; i++) {
  callArray(sArr[i]); //function call
}

***end: 1.354ms***

**


6

이것은 지금까지 가장 빠른 방법 인 것 같습니다 ...

var el;
while (el = arr.shift()) {
  el *= 2;
}

이것이 배열을 소비하고 그것을 먹고 아무것도 남겨 두지 않을 것이라는 점을 고려하십시오 ...


2
arr.shift();대신 arr.pop() 배열 반전을 피할 수 있습니다.
Tintu C Raju 5

1
웹 서비스 (예 : 채팅 서비스 또는 제품 카탈로그의 항목)에서 JSON을 얻는 경우 @Gargaroz 배열을 한 번만 사용해야하는 다른 상황은 예를 들어 간격을두고 많은 좌표를 얻는 차트 일 수 있습니다. 많은 예가 있습니다.
Sergio

쿨, 설명해 주셔서 감사합니다. 매우 친절합니다. 이런 종류의 루프를 활용하기위한 추가 예제를 찾을 수있는 방향으로 나를 가리킬 수 있습니까?
Gargaroz

1
현재 Chrome 53 및 Firefox 48에서는 가장 느린 방법 중 하나입니다. perfjs.info/array-iteration을
Pencroff

1
@Alireza 동의합니다. 저도 그 대답에 대한 의견이 있습니다.
세르지오

4

그것은 올해 2017 .

나는 약간의 테스트를했다.

https://jsperf.com/fastest-way-to-iterate-through-an-array/

while방법이 Chrome에서 가장 빠른 것 같습니다 .

왼쪽 감소처럼 보인다는 ( --i) 훨씬 더 빨리 다른 (보다 ++i, i--, i++파이어 폭스에서).

이 접근법은 평균적으로 금식됩니다. 그러나 배열을 역순으로 반복합니다.

let i = array.length;
while (--i >= 0) {
    doSomething(array[i]);
}

전달 순서가 중요한 경우이 방법을 사용하십시오.

let ii = array.length;
let i = 0;
while (i < ii) {
    doSomething(array[i]);
    ++i;
}

3
키워드 let를 사용하면 실제로 루프 성능 대신 범위 생성 성능을 비교합니다. 루프 let i = 0, ii = array.length에서 사용 for하면 for블록 내부의 변수에 대한 새로운 범위가 만들어 집니다. 귀하의 while예제는 while블록 내부의 변수에 대한 새로운 범위를 만들지 않으므로 더 빠릅니다. for 루프 var대신 대신 사용 let하면 2017 년 동안 for 루프가 여전히 빠르지 만 더 읽기 쉽습니다.
CGodo

다음은 내가 말하는 것에 대한 jsperf입니다
CGodo

이것은 Chrome에서만 발생하는 문제입니다. 다른 브라우저에서 var와 것은 let동일한 성능을 가지고 - stackoverflow.com/a/32345435/1785975
SeregPie

흥미 롭군 어쨌든 ' whileChrome에서 더 빠르다 '는 문구가 정확 하지 않습니다 . letChrome에서 해당 키워드의 성능 문제로 인해 사용하는 경우에만 해당됩니다 . var다른 브라우저를 사용 하거나 다른 브라우저와 함께 사용하는 경우 forwhile거의 동일 for하지만 벤치 마크에 따라 때로는 더 빠르며 더 작고 읽기 쉬운 imho입니다.
CGodo

2

나는 항상 첫 번째 스타일로 씁니다.

컴파일러가 배열에 대해 최적화하기에 충분히 똑똑하더라도 DOMNodeList를 사용하거나 계산 된 길이의 복잡한 객체를 사용하면 여전히 똑똑합니까?

배열에 대한 질문이 무엇인지 알고 있지만 모든 루프를 하나의 스타일로 작성하는 것이 좋습니다.


1
var arr = []; // The array
var i = 0;
while (i < arr.length) {
    // Do something with arr[i]
    i++;
}

i ++는 ++ i, --i 및 i--보다 빠릅니다.

또한 마지막으로 i에 액세스해야 할 때 arr [i ++]을 수행하여 마지막 행을 저장할 수 있습니다 (그러나 디버그하기는 어려울 수 있음).

다른 루프 테스트와 함께 여기에서 테스트 할 수 있습니다 : http://jsperf.com/for-vs-whilepop/5


1
현재 Chrome 53에서는 사실이지만 Firefox 48의 속도는 같습니다 -perfjs.info/array-iteration을
Pencroff


1

2017 년 9 월 현재이 jsperf 테스트 는 Chrome 60에서 가장 성능이 우수한 다음 패턴을 보여줍니다.

function foo(x) {
 x;
};
arr.forEach(foo);

누구나 재현 할 수 있습니까?


예, 가장 빠른 것 같지만 IE11에서 이것을 실행 해보십시오.이 옵션은 가장 느립니다. Firefox 55.03에서는 '오래된 버스트 캐시 된 len'이 12mil에 도달하여 3.3k 크롬과 비교했을 때 놀라운 성능을 발휘합니다. 모든 브라우저에서 일관된 성능을 유지하려면 모든 브라우저에서 가장 빠른 평균 루프를 사용해야합니다.
Plippie

0

거대한 배열을 반복하는 다른 방법을 시도했지만 배열 길이를 절반으로 줄이고 단일 루프에서 두 반쪽을 반복하는 것이 더 빠름을 알았습니다. 이 성능 차이는 거대한 배열 을 처리하는 동안 볼 수 있습니다 .

var firstHalfLen =0;
var secondHalfLen = 0;
var count2=0;
var searchterm = "face";
var halfLen = arrayLength/2;
if(arrayLength%2==halfLen)
{
   firstHalfLen = Math.ceil(halfLen);
   secondHalfLen=Math.floor(halfLen);
}
else
{
   firstHalfLen=halfLen;
   secondHalfLen=halfLen;
}
for(var firstHalfCOunter=0,secondHalfCounter = arrayLength-secondHalfLen;
    firstHalfCOunter < firstHalfLen;
    firstHalfCOunter++)
{
  if(mainArray[firstHalfCOunter].search(new RegExp(searchterm, "i"))> -1)
  {
    count2+=1;
  }
  if(secondHalfCounter < arrayLength)
  {
    if(mainArray[secondHalfCounter].search(new RegExp(searchterm, "i"))> -1)
    {
        count2+=1;
    }
    secondHalfCounter++; 
  }
}

위의 방법과 캐시 된 길이 for 루프 사이의 성능 비교 (timer.js 사용).

http://jsfiddle.net/tejzpr/bbLgzxgo/




0

while 루프는 for 루프보다 약간 빠릅니다.

var len = arr.length;
while (len--) {
    // blah blah
}

while 루프를 대신 사용하십시오



-1

내가 아는 가장 우아한 솔루션은지도를 사용하는 것입니다.

var arr = [1,2,3];
arr.map(function(input){console.log(input);});

46
루프를 반복하는 가장 느린 방법은 묻지 않습니다.
eoleary


-1

배열을 반복하는 가장 빠른 방법은 필터를 사용하는 것입니다. filter () 메소드는 제공된 함수로 구현 된 테스트를 통과하는 모든 요소로 새 배열을 작성합니다.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

const words = ['Floccinaucinihilipilification', 'limit', 'elite', 'Hippopotomonstrosesquipedaliophobia', 'destruction', 'present'];

const result = words.filter(word => word.length > 6);

console.log(new Date(), result);

내 경험으로는 항상 필터, 맵 등을 선호합니다.


문제는 어레이를 새 어레이로 복사하지 않고 최단 시간 내에 어레이를 반복하는 것입니다.
Rahul Kadukar

-1

2019 년 현재 WebWorker는 더 큰 데이터 세트에 대해 널리 사용되어 왔으며, 멀티 코어 프로세서를 완전히 활용하여 WebWorker를 사용하여 훨씬 빠르게 처리 할 수 ​​있습니다.

WebWorker를 데이터 처리에 훨씬 쉽게 사용할 수 있도록하는 Parallel.js 도 있습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.