prgrms-web-devcourse/FEDC4-Modern-React-Study

[1장][효리] 리액트 개발을 위해 꼭 알아야 할 자바스크립트

Closed this issue · 3 comments

퀴즈

효리는 다음 코드의 실행 결과에서 0 1 2의 결과를 원했다. 하지만 결과는 의도한 대로 나오지 않았다.
코드의 실행 결과를 적고, 잘못된 이유를 작성하시오. 또한 의도한 결과가 나오기 위한 코드를 작성하시오!

var funcs = []

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

for (var j = 0; j < funcs.length; j++){
    console.log(funcs[j]())
}

정답

코드의 실행 결과

3
3
3

잘못된 이유

반복문을 사용할 때 for 문 내 변수를 var로 선언하는 경우 문제 발생 확률이 커진다.
for 문의 코드 블록이 실행될 때마다 새로운 렉시컬 환경을 생성하기 때문이다.

  • for 문이 평가되면 새 렉시컬 환경을 계속 생성하고 실행 컨텍스트의 렉시컬 환경으로 교체한다.
  • 계속 쌓여쌓여 나간다. (스택이 쌓이는 게 아니다.)
  • for 문의 반복 실행이 모두 종료되면 for 문이 실행되기 이전의 렉시컬 환경으로 되돌린다.

var는 전역 변수이기 때문에 funcs[j]()의 호출 대상인 함수는 전역 변수인 i를 반환하게 된다.
또한 i가 2가 아닌 3인 이유는 for문을 다 돌고 나서 한 번 더 더해졌기 때문이다.
따라서 두 번째 for 문으로 함수를 호출해 출력하면 3 3 3의 결과가 나온다.

올바른 코드

  1. 즉시 실행 함수로 작성한다.
  2. var를 let으로 바꾼다.

- 모던 자바스크립트 딥다이브 413 ~ 414p

댓글 작성법

(다음과 같이 답을 작성해 댓글로 달아주세요)
<details>
<summary>정답</summary>
<div markdown="1">
정답 설명
</div>
</details>

222
var로 선언된 변수는 블록 레벨이 아닌 전역 레벨을 갖고
현재 i가 아닌 반복문이 종료된 i로 기억된다!

var funcs = []

for (let i = 0; i < 3; i++) { 
    funcs[i] = function() {
        return i 
    }
}

for (var j = 0; j < funcs.length; j++){
    console.log(funcs[j]())
}

실행결과 : 222

잘못된 이유
var로 선언된 변수는 블록 레벨이 아닌 전역 레벨을 갖는다

해결방법 1 let을 사용한다

var funcs = []

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

해결방법 2 즉시실행 함수를 사용한다

var funcs = []

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

for (var j = 0; j < funcs.length; j++){
    console.log(funcs[j]())
}

결과: 3 3 3
var는 함수 레벨 스코프여서 전역 변수로 관리된다. 이에 funcs를 출력할 때는 이미 값이 3이 되어있다.

블록 레벨 스코프인 let을 사용하자!

var funcs = []

for (let i = 0; i < 3; i++) { 
    funcs[i] = function() {
        return i 
    }
}

for (let j = 0; j < funcs.length; j++){
    console.log(funcs[j]())
}