Open-Closed Principle

[javascript] for문 사용법(최적화) 본문

Programming/JavaScript&Jquery

[javascript] for문 사용법(최적화)

대박플머 2016. 1. 13. 22:11

javascript에도 기타 다른 언어들과 같이 for문이 존제 한다. 

그런데 우리가 아무 생각없이(?) 하고 있이면서도 성능상에는 영향을 줄 수 있는(당연히 반복문이기 때문에 100만 루프이상을 이야기 하는 것이다.) 습관이 있다. 

기본적으로 자바스크립트의 for문 문법은 아래와 같다. 

구문

for ([initialization]; [test]; [increment])
   statement 

initialization : 선택 사항입니다. 이 식은 루프가 실행되기 전에 한 번만 실행됩니다. 

test : 선택 사항입니다. 부울 식입니다. test가 true이면 statement가 실행됩니다. test가 false이면 루프가 종료됩니다. 

increment :  선택 사항입니다. 식입니다. 증분식은 모든 루프의 끝에서 실행됩니다. 

statement : 선택 사항입니다. test가 true인 경우 실행할 하나 이상의 문입니다. 복합 문도 가능합니다. 



일반적인 for 루프 패턴은 다음과 같이 생겼다. 

1
2
3
for (var i = 0; i < myarray.length; i++){
    // myarray[i]를 다루는 코드
}
cs


우리는 늘 이런식으로 사용을 하지만 위에서 말했던 바와 같이 성능상에 조금(아주 조금일 수도 있다.) 영향을 주는 점이 있다. 

그것은 바로 루프를 반복할 때 마다 length에 접근한다는 점이다. 배열이 아니라 HTMLCollection이라면 이 때문에 코드가 느려질 수 있다. 

※ HTMLCollection은 리턴 결과가 복수인 경우에 사용하게 되는 객체다. 유사배열로 배열과 비슷한 사용방법을 가지고 있지만 배열은 아니다. 특징으로 HTMLCollection의 목록은 실시간으로 변경된다. 

위에서 언급한 바와 같이 목록을 실시간 질의라는 점에서 문제가 된다. 

즉 콜렉션의 length 속성에 접근할 때마다 실제 DOM에 질의를 요청하는 것과 같으며, DOM 접근은 일반적으로 비용이 크다. 

따라서 for 루프를 좀더 최적화하기 위해서는 아래와 같이 배열(또는 콜렉션)의 length를 캐시해야 한다.

1
2
3
for (var i = 0, max = myarray.length; i < max; i++){
    // myarray[i]를 다루는 코드
}
cs



이렇게 하면 length 값을 한 번만 구하고, 루프를 도는 동안 이 값을 사용하게 됩니다. HTMLCollection를 반복하여 접근할 때 length를 캐시하면, 사파리 3에서 2배, IE7에서 190배에 이르기까지 모든 브라우저에서 속도가 향상된다고 한다. (책에서 봄)

이 방법 말고도 좋은 방법이 있다. 바로 0으로 i--로 내려 가면서 비교 하는 것이다. 변수의 수 또한 주릴 수 있다. 
1
2
3
for (var i = myarray.length;i < 0; i--){
    // myarray[i]를 다루는 코드 
}
cs

이렇게 max변수가 없어 졌다. 

미미할 수 있는 최적화 이지만 가끔은 미미한것이 절실할 때가 있기도 하다.