for in / for of 와 enumerable, iterable 속성

조 은길·2022년 6월 17일
0

Javascript 정리

목록 보기
43/48
post-thumbnail

JS는 반복문이 최근 프로그래밍 언어들에 비해서 어려운 편이다.

아마 전통 for문을 보면, 처음 반복문을 접하는 사람들은 덜컥 겁부터 날 것이다.

그래서, JS는 신버전이 나오면서, 용도에 맞게 편하게 쓸 수 있는 반복문을 여러 개 만들었다.

이번 기회에 반복문들 총정리를 해보자.

for, forEach는 이전에 정리했으니, for in, for of 반복문을 알아봅시다.

그리고 함께 enumerable, iterable 이라는 속성도 알아보자!!


반복문의 용도

반복문은 용도가 2개라고 보면 된다.

  1. 코드 단순 반복

  2. 자료형에 담긴 자료들을 하나씩 꺼내고 싶을 때

사용한다.

그 중 for in 반복문을 먼저 살펴보자.


for in 반복문은 Object에 사용한다

Object 자료형에 저장된 자료들을 하나씩 꺼내고 싶을 때 사용한다.

let 오브젝트 = { name : 'Kim', age : 30 };

for (let key in 오브젝트) {
  console.log(오브젝트[key]);
}

이렇게 사용한다.

(key라는건 변수명이다. 개발자가 마음대로 작명하면 된다.)

그럼 반복문은 오브젝트라는 자료 내부 데이터 갯수만큼 반복하게 되며

반복할 때마다 key라는 변수는 name, age 이렇게 데이터의 key값이 된다.

그럼 반복시마다 변경되는 key 값을 이용하면 오브젝트 내의 자료를 모두 출력할 수 있다.

단순하게 오브젝트.key를 콘솔창에 출력하면 되는데, 변수명을 저렇게 쩜찍고 쓸 수는 없으니

오브젝트[key] 라고 사용하면 된다.

오브젝트에서 자료 꺼내기 끝!!


for in 반복문의 특징 1. enumerable한 것만 출력해준다

여러분이 object 자료형을 만들 때

{ name : 'Kim' } 이걸 저장하면 Kim 이라는 자료만 달랑 저장되는게 아니다.

Kim과 함께 비밀스러운 속성들 3개가 저장됩니다.

let 오브젝트 = { name : 'Kim', age : 30 };

console.log( Object.getOwnPropertyDescriptor(오브젝트, 'name') ); 

비밀스런 속성 3개를 출력해보고 싶으면 위처럼 쓰시면 됩니다.

그럼 콘솔창에 뭐 이런게 나오죠?

{value: "Kim", writable: true, enumerable: true, configurable: true} 

이것이 Kim과 함께 몰래 저장되는 속성들이다.

( 그래서 Object 자료형이 좀 무겁다 )

여기서 enumerable이라는게 있는데, 이게 true인 자료들만 for in 반복문이 출력할 수 있습니다.

이걸 강제로 false로 만들면 for in 반복문이 거른다.
=> 즉, 반복문을 돌려서, 출력되지 않는다.

아무튼 이런 동작원리를 가진게 바로 for in 반복문입니다.

  • enumerable을 번역하면 '셀수있는' 이라는 뜻이다.

for in 반복문의 특징 2. 부모의 prototype에 저장된 것도 출력해준다

object의 부모의 유전자에 있는 속성도 반복문으로 출력해준다.

진짜인지 한번 실험해보자.

class 부모 {
 
}
부모.prototype.name = 'Park';

let 오브젝트 = new 부모();

for (let key in 오브젝트) {
  console.log( 오브젝트[key] );
}

Park이라는 자료는 부모가 가지고 있는 것인데도 출력해준다.

이게 단점이다.

hasOwnProperty()

이런게 싫으다면 if문을 추가해줘야한다.


class 부모 {
 
}
부모.prototype.name = 'Park';

var 오브젝트 = new 부모();

for (var key in 오브젝트) {
  if (오브젝트.hasOwnProperty(key)) {
    console.log(오브젝트[key]);
  }
}

오브젝트.hasOwnProperty()라는 함수는

" 오브젝트가 이 key값을 직접 가지고 있냐? "라고 물어보는 함수이다.

갖고 있으면 true, 없으면 false를 뱉어준다.

그래서 내가 가진 것만 반복시키고 싶으면 이걸 꼭 써야한다.


for of 반복문

사용해봅시다. for in 반복문과 매우 유사하다.


var 어레이 = [2,3,4,5];
for (var 자료 of 어레이) {
  console.log(자료);
}

이러면 어레이 안에 있던 모든 자료를 하나씩 콘솔창에 출력할 수 있군요.

array 자료형 뿐만 아니라

array, 문자, arguments, NodeList, Map, Set 이라는 자료형에 적용할 수 있는 반복문입니다.

  • 이렇게 문자열로 출력해준다. 어떤 문자가 제일 많이 출력되는지 알아볼 때, 쓸 수 있지 않을까??

근데 정확히 말하면 iterable인 자료형들에만 적용가능한 반복문입니다.

iterable한 자료형이 뭐냐면,

[Symbol.iterator]() 이라는 일종의 메소드를 가지고 있는 자료형들을 뜻한다.

진짜 이런 괴상한게 있는지 출력만 해보도록 하자.


var 어레이 = [2,3,4,5];
console.log( 어레이[Symbol.iterator]() );

array 자료형 뒤에 붙이면 뭔가 출력되긴 하죠?

문자도 그렇다.

  • iterator
    실은 반복문 출력을 도와주는 일종의 함수인데, 실용성은 없어서 깊게 이해할 필요는 없고
    이걸 가지고 있으면 for of 반복문을 쓸 수 있구나~라고만 알면 된다.

for of는 NodeList라는 곳에도 사용할 수 있는데

우리가 흔히 document.getElementsByClassName()이나 document.querySelectorAll() 이런 셀렉터로 찾은 요소들이

[] 대괄호안에 담겨오는데 array는 아니고 NodeList라는 자료형이라고 부른다.

NodeList에 있는 HTML요소들을 하나씩 꺼내서 처리할 때, 매우 자주 쓸 수 있는 반복문이라고 보면 된다.

(하지만, for of의 호환성 주의)


연습문제

Q1. for of 반복문을 이용해서 2단부터 9단까지의 구구단을 콘솔창에 한번 출력해보십시오.

2 x 1 = 2

2 x 2 = 4

...

9 x 9 = 81

이런 문자를 쭉 9단까지 출력해보시면 되겠습니다.


let 데이터 = [1,2,3,4,5,6,7,8,9] 

for of는 array 이런거 반복문 돌릴 때 쓰랬으니 필요한 array데이터는 드림

  • 정답
let 데이터 = [1,2,3,4,5,6,7,8,9] ;

for ( let data of 데이터 ){
  // console.log(data);
  if(data>1){
    
    for(let i=1; i<=데이터.length; i++){
      let str = `${data}*${i} = `;
      console.log( str , data*i )
    }
  }
}

Q. 어떤 놈이 key값 마지막 부분에 오타를 섞어놨습니다.


var products = [
  {
    name1 : 'chair',
    price1 : 7000,
  },
  {
    name2 : 'sofa',
    price : 5000,
  },
  {
    name1 : 'desk',
    price3 : 9000,
  },
]; 

key값 마지막에 한자릿수 숫자가 섞여있으면 그걸 다 제거하고 싶습니다.

어떻게 코드를 짜면 될까요?

마지막 글자가 숫자인지 판단하는 방법도 잘 찾아봐야겠군요.

(예시)

array안의 object안에 들어있는

name1 : 'chair' 이게

name : 'chair' 이렇게 숫자만 깔끔하게 없어져야합니다.

  • 정답

isNaN(parseInt('123'))

이걸 사용하면 대충 이게 숫자형 문자인지 판단이 가능합니다.

NaN은 문자에 숫자연산하려고하면 나오는 이상한 자료형이며 isNaN은 NaN인지 판정해줍니다.

그래서 저기에 '123' 이걸 집어넣으면 false가 남습니다.

그래서 저기에 '가나다' 이걸 집어넣으면 true가 남습니다.

처음부터 반복문 돌리는게 익숙치않은 초보라면

하나만 하드코딩해보십시오 그리고 그걸 반복문돌리는게 훨씬 쉽습니다.

그래서 저도 테스트삼아서 object 자료 하나만 해봤습니다.


let 오브젝트 = {
  name1 : 'chair'
}

//마지막글자를 숫자로변환했을 때 NaN이 안나오면 (숫자면)
if (isNaN(parseInt('name1'.slice(-1))) == false ) {
    let newValue = 오브젝트['name1'];
    let newKey = 'name1'.slice(0, -1);  //맨 뒷 문자 제거 방법
    오브젝트[newKey] = newValue;

    delete 오브젝트['name1']; //원래있던 key 제거
}

console.log(오브젝트)

그래서 출력해보니 진짜 name1이 name으로 바뀌어있군요.

  1. name1 여기 가장 뒷자리 문자가 숫자인지 확인합니다.

  2. 그게 숫자면 일단 newValue, newKey를 만들어줍니다.

  3. newKey는 맨 뒷 문자를 제거해줍니다.

그리고 기존 오브젝트에 { newKey : newValue } 데이터를 추가해줍니다.

  1. 마지막으로 delete 키워드 쓰면 object에 있던 property 지울 수 있습니다.

아무튼 잘 되니 products array 자료 안에 있던 모든 object에 그거 쓰라고 반복문을 돌렸습니다.


let newValue;
let newKey;

for (let item of products) {
  for (let key in item) {
     //마지막글자를 숫자로변환했을 때 NaN이 안나오면 (숫자면)
     if (isNaN(parseInt(key.slice(-1))) == false ) {
       newValue = item[key];
       newKey = key.slice(0, -1); 
       item[newKey] = newValue;
       delete item[key]; 
     }
  }
}

console.log(products)

끝!

profile
좋은 길로만 가는 "조은길"입니다😁

0개의 댓글