for문과 for...in은 다르다
for(let i; i < arr.length; i++){
	console.log(arr[i]);
}

for(let i in arr) {
	console.log(arr[i]);
}

위 처럼 for … in을 for문의 축약 버전으로 사용하는 경우가 많은데 절대 그렇지 않다. MDN에 나온 for in에 대한 설명이다.

The for…in statement iterates over all enumerable properties of an object that are keyed by strings (ignoring ones keyed by Symbols), including inherited enumerable properties.

간단히 말하면 for in 문은 상속받은 속성을 포함한 객체의 enumerable한 속성을 반복하는 명령이다. 이게 배열 순회 사용에 적합하지 않는 이유는

  1. 상속받은 속성도 순회한다: 다음과 같이 prototype에 의도치 않은 속성이 추가될 경우 이 값도 순회 대상이 되어버린다.

     let arr = [1,2,3];
     Array.prototype.foo = 'bad'
     for(let i in arr) { console.log(arr[i])};
     // 1
     // 2
     // 3
     // bad
    
  2. index의 순서를 보장하지 않는다: ECMA spec에 따르면 for…in은 다음 property를 찾을 때 객체의 [[Enumerrable]] 속성이 true인 프로퍼티를 찾는다고만 되어있다. 이는 1의 다음이 2라는 보장이 안되어 있다는 말. 만약 배열을 순회할 때 순서가 중요하다면 for…in은 좋은 정답이 될 수 없다.

그럼 왜 쓰나?

for…in은 객체의 프로퍼티를 순회하기 위해 만들어졌기 때문에 배열을 순회하는 용도로는 적합하지 않다. 대신 객체의 프로퍼티를 쉽게 확인할 수 있기 때문에 디버깅 용으로 적합하다.

배열을 순회하고 싶다면 for문이나 forEach, for…of를 사용하자.

참고자료

http://www.ecma-international.org/ecma-262/5.1/#sec-12.6.4

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for…in