블로그에 가장 처음 썼던 글이 var, let, const 의 차이점이었음
이번 프로그래머스 문제를 풀면서 for문에서도 변수를 let으로 선언해줘야 한다는 점을 깨달음
for문을 사용할 때 조건식 영역에서 var을 사용할 때와 let을 사용할 때 결과 값이 다르게 나옴
var, let, const 각각의 변수는 유효범위(scope)를 가지는데 var은 function scope, let은 block scope를 가짐
block scope인 변수는 블록 안에서 선언되면 블록 밖에서 참조 불가! (if문, for문 에서 보이는 대괄호{}가 블록임)
//블록 안에서 선언, 블록 밖 참조
for (let i = 0; i < 10; i++){
let add1 = 1;
}
console.log(add1); //Uncaught ReferenceError: add1 is not defined
[for 문에서 변수 참조]
1. var 변수 참조
- for 문 밖(블록 밖)에서도 변수 참조 가능. 결과적으로 5가 출력됨
for (var i = 0; i < 5; i++){
console.log(i); // 0, 1, 2, 3, 4
}
console.log(i) // 5 (for 문에서 4까지 돌고 4에 ++ 한 후 for 문에서 빠져나옴)
2. let 변수 참조
- for 문에서 let 으로 변수 선언할 때, for 문 밖(블록 밖)에서 변수 참조 불가
for (let i = 1; i < 5; i++){
console.log(i); // 0, 1, 2, 3, 4
}
console.log(i); // i is not defined
[for 문 안에서 함수 사용시]
1. var 사용
function findUsers(ids) {
for (var i in ids) {
findUser(ids[i], function (user) {
console.log(i, "번째 사용자를 출력합니다.");
console.log(user);
});
}
}
[코드실행]
findUsers([3, 7, 29, 105]);
[결과]
3 번째 사용자를 출력합니다.
{ id: 3, name: '사용자 #3' }
3 번째 사용자를 출력합니다.
{ id: 7, name: '사용자 #7' }
3 번째 사용자를 출력합니다.
{ id: 29, name: '사용자 #29' }
3 번째 사용자를 출력합니다.
{ id: 105, name: '사용자 #105' }
모든 사용자에 대해 동일한 3 번째 사용자를 출력함
왜?
1. var 를 이용해 i 를 선언함
2. var 로 선언할 때 해당 변수는 자바스크립트 엔진이 함수 최상단으로 호이스팅함
3. 따라서 결과적으로 이렇게 해석됨
function findUsers(ids) {
var i;
for (i in ids) {
findUser(ids[i], function (user) {
console.log(i, "번째 사용자를 출력합니다.");
console.log(user);
});
}
}
- i 가 루프를 도는 내내 계속 공유되는 것 알 수 있음
- for 문에서 각 콜백 함수를 넘길 시점에는 i 값이 다름
- 각 콜백 함수가 실행될 시점에는 for 루프가 이미 끝나 i 가 배열의 마지막 원소 인덱스로 변경된 이후임
- 즉 var 의 변수 호이스팅과 콜백 함수의 non blocking 성질이 위와 같은 결과를 만들어 냄
그렇다면, 해결방법은?
var 대신에 let 이용해 변수 선언하기! (let 은 변수 호이스팅x, 블록 스코프 가짐)
function findUsers(ids) {
for (let i in ids) {
findUser(ids[i], function (user) {
console.log(i, "번째 사용자를 출력합니다.");
console.log(user);
});
}
}
[결과]
0 번째 사용자를 출력합니다.
{ id: 3, name: '사용자 #3' }
1 번째 사용자를 출력합니다.
{ id: 7, name: '사용자 #7' }
2 번째 사용자를 출력합니다.
{ id: 29, name: '사용자 #29' }
3 번째 사용자를 출력합니다.
{ id: 105, name: '사용자 #105' }
- for 루프의 매 패스마다 새로운 i 가 선언되어 0, 1, 2, 3 차례로 할당됨
- 서로 독립된 블록 스코프를 가지며 결과적으로 각 콜백 함수는 서로 다른 i 값을 인자로 받음
[참고]
https://www.daleseo.com/js-es2015-let-in-for/
https://fromnowwon.tistory.com/entry/for%EB%AC%B8-let
'개발 > Javascript' 카테고리의 다른 글
[JS] 배열에서 최대값, 최소값 구하기 (1) | 2022.09.21 |
---|---|
[JS] 전위 연산자, 후위 연산자 (0) | 2022.08.23 |
[JS] 형 변환 (0) | 2022.08.20 |
[JS] substring(), slice() 비교 (0) | 2022.08.20 |
[JS] var, let, const 차이점 + 호이스팅, TDZ (0) | 2022.08.19 |