ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [TIL]Day 21. for/in 을 사용하면 안되는 이유!!!(in JS)
    IT 지식 2020. 10. 5. 13:12
    728x90

    오늘은 wecode에서 code kata를 하고 나서 알게 된 for/in 문의 사용법에 대해 포스팅하도록 하겠습니다.

     

    1. 문제의 시작

     

    -----------------------------------------------------------------------------------------------------------------------------------

    더보기

    * 문제

    twoSum함수에 숫자배열과 '특정 수'를 인자로 넘기면,

    더해서 '특정 수'가 나오는 index를 배열에 담아 return해 주세요.

     

    nums: 숫자 배열

    target: 두 수를 더해서 나올 수 있는 합계

    return: 두 수의 index를 가진 숫자 배열

     

    예를 들어,

    nums은 [4, 9, 11, 14] target은 13 nums[0] + nums[1] = 4 + 9 = 13 이죠? 그러면 [0, 1]이 return 되어야 합니다.

    -----------------------------------------------------------------------------------------------------------------------------------

     

    이 문제에 대해 접근하면서 맨 처음 떠올린 생각은 for/in문을 통해 반복해야겠다는 생각이었습니다. 그래서 처음엔 이런 식으로 코드를 작성했었습니다.

     

    const twoSum = (nums, target) => {
        for (let i in nums) {
          for (let j = i + 1; j < nums.length; j++) {
            if ((nums[i] + nums[j]) === target) {
              return [i, j];
            }
          }
        } 
    }

     얼핏 보기에는 문제가 없이 잘 될 것 같습니다. 실제로 이 코드를 실행해도 아무런 오류 없이 실행됩니다. 하지만 원하는 결과값이 도출되지 않습니다. 계속해서 undefined만 return 되었습니다.

     

    그리고 디버깅을 하던 중 for/in 문을 사용하지 않고 단순한 for 문을 사용하니 문제가 해결되었습니다.

     

    const twoSum = (nums, target) => {
        for (let i = 0; i < nums.length; i++) {
          for (let j = i + 1; j < nums.length; j++) {
            if ((nums[i] + nums[j]) === target) {
              return [i, j];
            }
          }
        } 
    }

     

    도대체 왜 이런 것이었을까요??

     

     

    2. for/in의 치명적 단점?!

     

    for/in에 대한 MDN 문서를 보면 다음과 같이 되어 있습니다.

     

    더보기

    설명

    for...in문은 열거 가능한 non-Symbol 속성에 대해서만 반복합니다.
    Array나 Object 등 내장 constructor를 통해 만들어진 객체는  String의 indexOf()Object의 toString()와 같이 Object.prototype, String.prototype 로부터 열거가 가능하지 않은 속성들을 상속해왔습니다. for...in문은 객체 자체의 모든 열거 가능한 속성들과 프로토타입 체인으로부터 상속받은 속성들에 대해 반복할 것입니다. (더 가까운 프로토타입의 속성들이 프로토타입 체인 객체로부터 더 멀리 떨어진 프로토 타입의 속성보다 더 우선합니다.)

     

    여기에서는 해결책을 찾을 수 없어 좀 더 내려가다보니 다음과 같은 내용이 있었습니다.

     

     

    'Note: for...in은 인덱스의 순서가 중요한 Array에서 반복을 위해 사용할 수 없습니다.'

     

     

    for/in 은 반복문을 간단하게만 만들어주는 문법이라고 생각했던 저에게 이것은 예상치 못한 변수였습니다! 그리고 이 이유로 인해서 제 코드가 제대로 작동하지 않은 것이었습니다.

     

     

    javascript의 for/in 문은 임의의 순서로 배열을 반복하는 특성을 가지고 있습니다.

     

     

    이 특성은 순서가 중요하지 않은 배열이나 객체에서는 큰 문제가 되지 않습니다. 보통의 경우 배열을 반복하는 것만이 중요할 뿐 순서를 신경쓰지 않다보니 대부분의 코드에서는 문제없이 작동되는 것이었습니다.

     

    하지만 오늘 문제의 경우에는 구체적인 index 값을 도출하기 위해 i와 j의 값을 도출하는 것이 중요했고, 그만큼 배열이 진행되는 순서가 중요했습니다. 

     

    더보기

    배열의 반복과 for...in ( from MDN 문서)

    Note: for...in은 인덱스의 순서가 중요한 Array에서 반복을 위해 사용할 수 없습니다.

    배열 인덱스는 정수로 된 열거 가능한 속성이며, 일반적인 객체의 속성들과 같습니다. for...in은 특정 순서에 따라 인덱스를 반환하는 것을 보장할 수 없습니다. for...in반복문은 정수가 아닌 이름을 가진 속성, 상속된 모든 열거 가능한 속성들을 반환합니다.

    반복되는 순서는 구현에 따라 다르기 때문에, 배열의 반복이 일관된 순서로 요소를 방문하지 못할 수도 있습니다. 그러므로 방문의 순서가 중요한 배열의 반복시에는 숫자 인덱스를 사용할 수 있는 for 반복문을 사용하는 것이 좋습니다.(또는 Array.prototype.forEach()for...of를 권장합니다.)

     

    그렇다면 왜 for/in 문이 필요한 것일까요??

     

     

    3. for/in을 사용해야 하는 이유

     

    더보기

    왜 for...in을 사용합니까? (from MDN 문서)

    for...in이 객체의 반복을 위해 만들어졌지만, 배열의 반복을 위해서는 추천되지 않고,  Array.prototype.forEach(), for...of가 이미 존재합니다. 그러면 for...in은 어떻게 사용하는 것이 좋을까요?

    이것은 쉽게 객체의 속성을 확인(콘솔이나 다른 방법으로 출력)할 수 있기 때문에 실질적으로 디버깅을 위해 사용될 수 있습니다. 배열이 데이터의 저장에 있어서는 더 실용적이지만, 키-값 쌍이 선호되는 데이터의 경우(속성이 "key"의 역할을 함) 특정 값을 가진 키가 있는지 확인하려는 경우에 for...in을 사용할 수 있습니다.

     

     

    위의 MDN문서를 참조해본다면 for/in은 주로 객체의 반복을 위해 활용하는 것이 좋아보입니다. 객체를 반복한다는 것은 키-값의 매칭이 중요하지 순서나 인덱스 값이 중요한 것은 아니니까요. 또 디버깅을 하기 위한 용도로 사용하기에도 좋아보입니다. 객체의 속성을 확인할 수 있다는 특징이 디버깅에 큰 도움이 되는 것 같습니다.

     

    4. 마치며

     

    오늘은 쉽게 실수할 수 있는 for/in 문의 사용법에 대해 알아보았습니다. 아무때나 이 용법을 사용해선 안되고 주로 객체에 활용해야 한다는 것이 중요 포인트였네요. 마지막으로 w3schools에 있는 반복문의 종류와 특징에 관한 내용을 인용하며 이번 포스팅 마무리하도록 하겠습니다.

     

     

     

    • for - loops through a block of code a number of times

    • for/in - loops through the properties of an object

    • for/of - loops through the values of an iterable object

    • while - loops through a block of code while a specified condition is true

    • do/while - loops through a block of code once, and then repeats the loop while a specified condition is true

    Note: Do not use the for/in statement to loop through arrays where index order is important. Use the for statement instead.

    728x90

    댓글

Designed by Tistory.