for과 for-in 패턴.md

이 글은 "JavaScript Patterns" 책을 공부하며 요약해 쓴 글입니다.


for

for 루프는 배열, arguments, HTMLCollection 등 배열과 비슷한 객체를 순회한다.

 

*HTMLCollection: HTML 요소들의 리스트로 유사배열객체이다.

 

 

일반적인 for 문

 

이 패턴은 루프 순회시마다 arr의 length에 접근한다.

 

만약 arr이 배열이 아닌 HTMLCollection이라면 코드가 느려질 수 있다.

  • 실제 DOM의 접근 비용은 일반적으로 크다.
  • HTMLCollection 객체의 length 속성 접근은 실제 DOM에 질의를 요청하는 것과 같다.
  • 실제 DOM 질의는 실시간으로 처리된다. 브라우저는 DOM 조작이 일어나면 다시 브라우저에 렌더링하는데에 수 많은 처리 과정을 거치는데, 이는 많은 비용이 요구된다. (reflow를 참고)

arr.length의 값이 10000이라면 브라우저를 10000번 렌더링하는 것과 같다.

 

여러 최적화 방법들

 

1. 배열(또는 콜렉션)의 length를 캐시
 

HTMLCollection 객체의 length 값을 초기화 변수에 저장하여 한 번의 DOM 접근만이 이루어진다.

 

2. 변수 갯수 줄이기, 배열을 거꾸로 순회
 

length 변수를 없애고, 배열의 카운트를 감소시켜 0으로 내려간다. (미세 최적화)

  • 0과 비교하는 것이 배열의 length 또는 0이 아닌 값과 비교하는 것보다 대게 더 빠르다.
  • 성능이 결정적인 요소가 되는 작업에서 사용하는 것을 권장

for-in

for-in 루프는 배열이 아닌 객체를 순회할 때 사용해야 한다.

  • 자바스크립트의 배열은 객체이기 때문에 for-in 루프를 통해 순회할 수 있지만, 권장사항이 아니다.
  • 배열 객체에 사용자가 정의한 기능이 추가되면 논리적인 오류가 발생할 수 있다.
  • 열거 순서가 정해져있지 않다. 실제로 배열은 for-in이 아닌 for 루프로 순회하는 것이 좀 더 빠르다.
 

 

일어날 수 있는 오류 피하기

코드 내에 'Object.prototype.메서드명'이라는 사용자가 지정한 메서드가 모든 객체에 추가되었다고 가정하자.

이 메서드 프로퍼티는 프로토타입 체인을 따라 상속되어 모든 객체의 프로퍼티로 사용할 수 있게 된다.

이 문제로 인해 어떤 객체가 for-in 루프로 순회하는 과정에서 의도치 않게 메서드가 사용될 수 있다.

ex)

 

 

1. hasOwnProperty() 사용

Object의 hasOwnProperty 메서드를 사용하여 객체 변수의 고유 프로퍼티만을 사용할 수 있다.

 

 

2. Object.prototype.hasOwnProperty.call() 사용

이 패턴은 만약 fruits 객체의 hasOwnProperty 메서드를 오버라이딩 했을 경우에도, 온전한 hasOwnProperty 메서드를 사용할 수 있게 해준다.

 

 

3. Object.prototype.hasOwnProperty 캐시

프로퍼티 탐색이 체인을 따라 Object까지 거슬러 올라가지 않게 하기 위해, 지역 변수를 사용하여 메서드를 캐시한다.

 

 

hasOwnProperty()를 사용하지 않았다고 해서 오류가 발생하지는 않으며, 루프 속도가 약간 감소될 수 있지만, 객체와 객체 프로토타입 체인의 내용을 보장할 수 없다면 hasOwnProperty()로 확인하는 것이 좀 더 안전한 방법이다.

+ Recent posts