[Javascript] for in vs for of

박기영·2022년 11월 1일
0

Javascript

목록 보기
16/45

for in

for in은 객체에 대한 반복을 할 때 주로 사용된다.
예시를 살펴보자.

let testObj = {
  yaya: 1000,
  ho: 133,
  naldo: 184,
  nolja: 235,
  toss: 49,
};

for (let key in testObj) {
  console.log(key);
}

이런 식으로 객체의 key에 접근할 때 사용된다.

결과는 아래와 같다.

yaya
ho
naldo
nolja
toss

key가 나온다는 점에 주의하자.
만약 key,value를 모두 사용하고자 한다면 다음과 같이 사용할 수 있겠다.

for (let key in testObj) {
  console.log(key, testObj[key]);
}

그렇다면 결과는?

yaya 1000
ho 133
naldo 184
nolja 235
toss 49

key, value가 알맞게 출력되는 것을 확인 할 수 있다.

enumerable한 프로퍼티만 가능하다

for inenumerable한 프로퍼티에 대해서만 작동하는 문법이다.
...네...?? 그걸 제가 어떻게 알아요 ㅠㅠ

알 수 있는 방법이 있다.
Object.getOwnPropertyDescriptor() 메소드를 사용하면 된다.
사용법은 아래와 같다.

Object.getOwnPropertyDescriptor(obj, propertyName);

obj 자리에는 속성을 찾을 객체, propertyName에는 설명이 검색될 속성명을 작성하면 된다.

그럼 위 예시를 활용해서 실제로 사용해보자.

Object.getOwnPropertyDescriptor(testObj, "yaya");

testObj라는 객체의 yaya라는 key의 설명을 출력해라!!
콘솔을 찍어보면 아래와 같다.

{ value: 1000, writable: true, enumerable: true, configurable: true }

오..enumerable이라는 keytrue라는 값이 들어있다.
즉, 이 프로퍼티는 enumerable하다는 것이다.

배열(Array)에 대하여 어떻게 동작하는가

문득, JS에서 배열 또한 object 속성이라는 것이 생각나서, 예시를 하나 만들어보았다.

let testArr = ["yaya", "ho", "naldo", "nolja", "toss"];

for (let prop in testArr) {
  console.log(prop);
}

결과는 어떨까?
결과를 보기 전에, 배열은 enumerable한지 먼저 살펴보자.

Object.getOwnPropertyDescriptor(testArr, "yaya");

과연 배열은 enumerable할까?

undefined

엥? 아니 그럼 배열은 for in 못 써요?
아니다.
배열에 대해서 Object.getOwnPropertyDescriptor()를 하려면 인덱스 번호를 적어야한다.

Object.getOwnPropertyDescriptor(testArr, 0);

0번 인덱스에 있는 프로퍼티에 대한 설명을 출력해라!!

{ value: 'yaya', writable: true, enumerable: true, configurable: true }

오 이번에는 제대로 출력된다!
enumerabletrue인 것을 확인 할 수 있다!
즉, 배열도 for in을 사용할 수 있다.

그럼 위에서 for in으로 콘솔을 찍은 값들을 살펴보자.

0
1
2
3
4

배열에 대해서는 인덱스가 출력되는 것을 확인 할 수 있다.
인덱스를 출력한다라...그렇다면 인덱스에 있는 값을 출력하려면 어떻게 해야할까?

for (let prop in testArr) {
  console.log(testArr[prop]);
}

이렇게 써주면 된다. 객체 타입 데이터에서 value를 뽑아내는 방법과 동일하다.
결과를 살펴보자.

yaya
ho
naldo
nolja
toss

짠! 드디어 배열의 원소가 출력이 된다.

prototype도 출력된다

다음 예시를 살펴보자.(이 예시는 hoon_dev님 블로그에서 가져왔습니다.)

let bookArray = [
  "자바스크립트 완벽하게 이해하기",
  32000,
  "훈이",
  "자바스크립트짱짱",
];

class Book {
  constructor(title, price, author, publisher) {
    (this.title = title),
      (this.price = price),
      (this.author = author),
      (this.publisher = publisher);
  }
}

Book.prototype.published_date = 20201220;
let book = new Book(...bookArray);

for (key in book) {
  console.log(`key : ${key} / value : ${book[key]}`);
}

결과를 살펴보자.

key : title / value : 자바스크립트 완벽하게 이해하기
key : price / value : 32000
key : author / value : 훈이
key : publisher / value : 자바스크립트짱짱
key : published_date / value : 20201220

마지막 줄에 있는 것은 객체에 들어있던 값이 아니었다.
published_dateprototype을 추가했더니 반복문에 같이 딸려 나온 것이다.

그러나 우리는 bookArray라는 객체의 값만 필요하므로, 이 상황은 좋지 않다.
어떻게 하면 prototype의 결과를 제외하고, 필요한 값들만 뽑아낼 수 있을까?

for (key in book) {
  if (book.hasOwnProperty(key)) {
    console.log(`key : ${key} / value : ${book[key]}`);
  }
}

바로 key의 존재 여부를 판단해주는 hasOwnProperty() 메소드를 사용하면 된다.
결과를 살펴보자.

key : title / value : 자바스크립트 완벽하게 이해하기
key : price / value : 32000
key : author / value : 훈이
key : publisher / value : 자바스크립트짱짱

이제 prototype에 의한 값은 출력되지 않는 것을 확인 할 수 있다!

for of

for of는 주로 배열의 반복에 대하여 사용한다.
꼭 배열에만 사용해야 되는 것은 아니고 반복 가능한 객체라면 사용할 수 있다.

반복 가능한 객체에만 사용 가능

반복 가능한 객체란 무엇인가?

for...of 명령문은 반복가능한 객체 (Array, Map (en-US), Set, String, TypedArray, arguments 객체 등을 포함)에 대해서 반복하고...
- MDN docs -

그렇다. 저런 데이터를 반복 가능한 객체라고 한다.
애매하다. 더 정확하게 반복 가능한 객체를 정의하면 다음과 같다.

[Symbol.iterator] 속성을 가지고 있는 것

이 것을 어떻게 확인할 수 있느냐?

testArr[Symbol.iterator]();

알고싶은 대상(여기서는 testArr라는 변수)에 [Symbol.iterator]()을 사용하면 된다.
결과를 콘솔에 찍어보면, 다음과 같은 결과가 나온다.

Object [Array Iterator] {}

이런 결과가 나오면 이 객체는 반복 가능한 객체이다.

이제 사용 조건을 알았으니 사용법을 알아보자.

let testArr = ["yaya", "ho", "naldo", "nolja", "toss"];

for (let item of testArr) {
  console.log(item);
}

for in의 사용법과 똑.같.다.
다른 것은 결과뿐이다.
결과를 살펴보자.

yaya
ho
naldo
nolja
toss

for in 때와는 다르게 이번에는 바로 배열 원소에 접근할 수 있다!

객체에는 적용 가능한가?

그렇다면 객체에 대해서도 살펴보자.

let testObj = {
  yaya: 1000,
  ho: 133,
  naldo: 184,
  nolja: 235,
  toss: 49,
};

console.log(testObj[Symbol.iterator]());  // 에러!!

객체에 대해서는 불가능하다.
객체는 반복 가능한 객체가 아니기 때문이다.

성능 비교

사용 방향이 다른듯 비슷한 두 방법에 대해서 알아봤다.
하지만 결국 중요한 것은 성능!
어떤 방법이 더 빠른지 살펴보자.

아래 이미지는 길이가 100인 배열에 대하여 테스트를 진행한 성능 지표이다.

참고 이미지

참고 이미지

for in이 더 좋은 성능을 보인다..!
그러나 for in은 성능 이전에 다양한 문제가 있었다.
결국 성능 비교에 대해, 어떤 방법이 더 좋은 방법인지 가려내기가 어렵다.

객체에는 for in, 배열 등에는 for of를 사용하는게 맞는 것 같다.

참고 자료

hoon_dev님 블로그
kkd927님 게시글
for in - MDN docs
Object.getOwnPropertyDescriptor() - Javascript Info
Object.getOwnPropertyDescriptor() - MDN docs

profile
나를 믿는 사람들을, 실망시키지 않도록

0개의 댓글