• 카테고리

    질문 & 답변
  • 세부 분야

    프로그래밍 언어

  • 해결 여부

    해결됨

첫번째 for문에서 i값 5가 5번 출력 되는 이유

21.01.22 13:30 작성 조회수 155

0

var arr = []
for(var i = 0; i < 5; i++){
    arr[i] = function(){
        return i; 
    }
}

이 때 return i는 5보다 작은 수인 4가 되서, 값 4가 담깁니다.
var arr = [0,1,2,3,4]가 됩니다.

즉,배열은 for문 때문에 0,1,2,3,4까지 담기고
return i는 for문이 종료되는 시점의 i값을 리턴하기 때문에 4가 되는 것이죠.
그런데,

for(var index in arr) { console.log(arr[index]()); }


for in문으로 arr 배열에 있는 인덱스 번호만큼
콘솔창에서 arr[index]를 출력하라고 하죠,

첫번째 for문의 리턴값을 현재 4가 담겨져 있고
4의 ***index*** 번호는 5번 입니다.
즉 arr=[0,1,2,3,4] 배열 중에 숫자 4 값의 자리번호(index)번호는
5번인것이죠.

그래서

배열의 인덱스 수(5번) 만큼 for in문에서 콘솔이
5회 출력되고, 0부터 4번까지의 인덱스번호인 5번이 출력되서

5번이 5회 출력된 값이 나온거라고 이해 했습니다.

답변 3

·

답변을 작성해보세요.

6

드로우님의 프로필

드로우

2021.01.22

for(var index in arr) {
    console.log(arr[index]());
}

위 코드를 실행 시키면 차례대로 arr[0]() ~ arr[4]() 이런식으로 함수를 실행시키게 됩니다.
하지만 각 배열에 담긴 함수는 전역변수 i를 참조하고 i를 리턴하고 있죠. 그래서 최종적으로 5까지 증가된
전역변수 i가 5번 출력되는 겁니다.
즉, arr[4]가 5를 담고 있는게 아니라 0~4 인덱스 배열 전부 전역변수 i를 참조하고 있는 겁니다.

조금 잘못 이해하신 것 같아서 제가 다른 질문글에 답글 달아놓은 부분 다시 끌어올려 여기에 남깁니다.

우선 이런 문제는 var 의 문제점이라 볼 수 있습니다.
es6(es2015)부터는 이런 문제때문에 var 대신 constlet 을 쓰자고 지향하고 있습니다.

for (var i = 0; i < 5; i++) {}
console.log(i);

우선 위에 방식으로 for 문 안에 var i를 선언하고 바깥에서 console.log(i) 를 호출하면 이상하게
오류 없이 호출되는 걸 볼 수 있습니다.
그 이유는 var 선언 방식이 block scope가 아니라 function 단위 scope이기 때문에
for문이 끝났음에도 여전히 전역변수로써 유효하기 때문입니다.
전역변수로 선언되어 버리는 부분이 어떤 문제를 일으키는지 아래 코드를 보면서 살펴보죠. 

* 영상에서의 코드

var arr = [];
for (var i = 0; i < 5; i++) {
  arr[i] = function () {
    return i;
  };
}

for (var index in arr) {
  console.log(arr[index]());
}

                                                                                   ↓

arr[0] = function () {
  return i;
};
arr[1] = function () {
  return i;
};

...

arr[4] = function () {
  return i;
};

이런식으로 배열내 각 인덱스에 할당되겠죠. 하지만 return 값은 할당될 때의 
i 값이아니라 전역변수 i 를 참조하고 있기 때문에 이 함수들을 호출하면 계속해서
전역변수 i 의 최종 값인  5를 불러오게 되는 겁니다.
첫번째 for 문에서 루프가 끝나면서 전역변수 i의 값이 이미 5가 되었으니까요.

* 클로저를 사용하면 정상작동 하는 이유

for (var i = 0; i < 5; i++) {
  arr[i] = function (index) {  // index는 parameter이며, 전달인자로 받은 i 값이 들어있다.
    return function () {
      return index;
    };
  }(i);  // 전달인자(argument)로 i를 주고있다.
}

for (var func of arr) {
  console.log(func());
}

클로저(closure)를 사용하여 전달인자(argument)로 i 값을 주면 배열에 각 함수가 할당될 때 그 때의 i 값을 매개변수(parameter)로 받기 때문에 지역변수를 사용한 것 같은 효과가 나게되는 것이죠.

1

이동민님의 프로필

이동민

2021.07.13

자바스크립트를 할 줄은 알지만 기초가 부족한 제가 보기에, 본 강의는 2014년에 만들어진 강의이다보니 현재의 문법(ES6)과는 맞지 않는 부분이 다소 있습니다. 특히 클로저부분은 스킵하시고 구글 검색으로 추가 학습하시는 것을 권합니다.

아래는 제가 추천하는 사이트입니다. 아래 링크에서 "4. 오래된 'var'" 항목을 참고하시기 바랍니다

https://ko.javascript.info/advanced-functions

0

WS IM님의 프로필

WS IM

2021.06.11

반복문에서 var 대신 let을 쓰면 의도한대로 잘 나오네요

var arr = [];
for (let i = 0; i < 5; i++) { // var 대신 let 쓰면 의도한대로 출력
  arr[i] = function () {
    return i;
  };
}

for (var index in arr) {
  console.log(arr[index]());
}