[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의 결과가 나온다.
올바른 코드
- 즉시 실행 함수로 작성한다.
- 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]())
}