October 16, 2021
프론트엔드 개발을 위한 자바스크립트(feat. VanillaJS)에 참여하면서 공부한 내용을 정리합니다.
이번 글에서는 for문의 변수 선언문에서 var를 사용했을때 발생하는 문제, 그리고 해결방법에 대해 정리하겠습니다
const numbers = [1, 2, 3, 4, 5];
for (var i = 0; i < numbers.length; i++) {
setTimeout(function() {
console.log(`number index ${i}`);
}, 1000);
}
위의 코드는 아래처럼 동작합니다.
const numbers = [1, 2, 3, 4, 5];
var i;
for (i = 0; i < numbers.length; i++) {
setTimeout(function() {
console.log(`number index ${i}`);
}, 1000);
}
var
는 함수 레벨 스코프
를 가지기 때문에 var
로 선언한 i
는 전역변수가 됩니다전역변수
i
는 계속 증가
됩니다i
를 참조합니다 number index 5
가 5번 찍히게 됩니다.var로 선언한 i는 for문에서만 유효한 것이 아닙니다. 전역변수가 되어 코드 전체에 영향을 미치게 됩니다.
let
let
키워드로 선언한 변수를 사용하면 for문의 코드 블록이 반복 실행될 때마다 for문 코드 블록의 새로운 렉시컬 환경이 생성됩니다for문이 반복될 때마다 독립적인 렉시컬 환경을 생성하여 식별자 값을 관리합니다
렉시컬 환경
: 식별자
와 식별자에 바인딩된 값
그리고 상위 스코프에 대한 참조를 기록
하는 자료구조입니다렉시컬 스코프
: 자바스크립트 엔진은 함수를 어디에 정의했는지에 따라 상위 스코프를 결정합니다. 이를 렉시컬 스코프(정적 스코프)라 합니다const numbers = [1, 2, 3, 4, 5];
for (let i = 0; i < numbers.length; i++) {
setTimeout(function() {
console.log(`number index ${i}`);
}, 1000);
}
24.6
클로저는 함수와 함수가 선언된 렉시컬 환경과의 조합이다.
- mdn 클로저
클로저
때문에 가능한 것입니다.
클로저
라고 합니다[[Environment]]
에 자신이 정의된 환경, 즉 상위 스코프의 참조를 저장합니다24.3
IIFE
사용 (예전에 사용한던 방법)IIFE
가 내부의 setTimeout 안에서 사용되는 콜백 함수는 자신의 상위 스코프를 기억하는 클로저입니다.
매개변수로 전달된 i
는 for문이 종료되고 실행될 콜백 함수의 상위 스코프에 존재합니다const numbers = [1, 2, 3, 4, 5];
for (var i = 0; i < numbers.length; i++) {
(function(i, number) {
setTimeout(function() {
console.log(`number [${i}] ${number}`);
}, 1000);
})(i, numbers[i]);
}
forEach
사용const numbers = [1, 2, 3, 4, 5];
numbers.forEach((number, index) => {
setTimeout(() => {
console.log(number);
}, 1000);
});
변수 i의 스코프를 제한하고있다