변수의 특징 중 Hoisting, 전역변수, 참조에 대해 알아보자
// var 나이;
function 함수(){
(...)
}
(...)
var 나이 = 30; // 나이 = 30;
위 예시처럼 변수의 선언을 변수 범위 맨위로 끌고 오는 현상을 Hoisting 현상이라고 한다
변수를 만나면 선언부분을 강제로 맨 위로 끌어올리는 것
이런 현상이 일어나는 이유는 딱히 없다 JS 언어 자체가 그렇기 때문
// var 나이;
console.log(나이); // undefined
var 나이 = 30;
console.log(나이); // 30
변수의 Hoisting 현상 때문에 변수 선언 전에 console 창에 출력해도 에러가 나지 않는다
변수뿐만 아니라 함수도 Hositing 됨
💡 함수실행을 함수선언 전에 해도 상관없다 => 함수실행 위치는 상관없음
let, const 변수는 Hoisting시 undefined가 자동으로 할당되지 않기 때문에 에러가 출력됨 (temporal deadzone / uninitialized 라고 부름)
function 함수(){} : 전부 Hoisting 됨
var 함수 = function(){} : 선언 부분만 Hoisting 됨
함수();
var 함수 = function(){
console.log(안녕);
var 안녕 = 'Hello';
}
Q. 뭐가 출력될까?
🔑 에러
👉 var 함수 부분만 Hoisting 되므로 함수();를 호출할 때 함수 변수는 function이 할당되지 않은 상태!
var 나이 = 20, 이름 = 'ㅁ', 성별; 처럼 JS는 한 줄로 여러 변수를 만들 수 있다
👉 모든 곳에서 쓸 수 있는 변수
var 나이 = 20;
function 함수(){
console.log(나이);
}
함수();
위 예시처럼 밖에서 선언한 변수는 함수 안에서 그대로 사용할 수 있다
가장 밖에 선언된 변수를 전역변수라고 한다
그 외는 지역변수
var 나이 = 20;
window.이름 = '김';
window는 JS 기본 함수를 담은 object 또는 HTML DOM의 모음
window로 만든 전역 변수 안에는 값뿐만아니라 함수를 넣어도 된다
💡 전역변수 만드는 방법 중 제일 선호되는 방식
if (true){
let a = 1;
var b = 2;
if(true){
let b = 3;
}
console.log(b);
}
Q. 위 예시는 콘솔창에서 어떻게 나올까?
🔑 2
👉 let 변수의 범위는 { } 이기 때문에 두번째 if문은 없다고 봐도 무방함
따라서 콘솔창에 2가 출력된다
let a = 1;
var b = 2;
window.a = 3;
window.b = 4;
console.log(a + b);
Q. 무엇이 출력될까?
🔑 5
👉 b는 전역변수이므로 window.b = 4로 재할당을 해주면 값이 4로 변한다
하지만 a는 let으로 선언된 변수이기 때문에 window.a = 3으로 재할당을 해도 1로 출력된다
가장 가까운 범위에 있는 것을 출력하려고 하기 때문
for (var i = 0; i < 5; i++){
setTimeout(function(){ console.log(i) }, i * 1000);
}
Q. 출력되는 결과는 모두 5인데 왜그럴까?
🔑 위 코드에서 setTimeout문은 바로 실행되는 코드가 아니라 1~5초 뒤에 실행되는 코드. for문 위에 i가 전역변수의 형태로 반복문이 다 실행된 후의 값인 5로 (var i = 5) 남아있다
1~5초 후 console.log(i) 코드를 실행하기 위해 i를 찾으면 전역변수 i의 값은 5가 나온다 그래서 모두 5가 출력됨
💡 해결방법은 다음과 같다
for (var i = 0; i < 5; i++){
let i = 0;
setTimeout(function(){ console.log(i) }, i * 1000);
}
이렇게 하면 1~5초 후 i를 찾을 때 for문 안에 있는 let i를 사용할 수 있다
let 변수 활용!
var 버튼들 = document.querySelectorAll('button');
var 모달창들 = document.querySelectorAll('div');
for (var i = 0; i < 3; i++){
버튼들[i].addEventListener('click', function(){
모달창들[i].style.display = 'block'
});
}
Q. 에러가 나는 이유는 무엇일까?
🔑 for문은 3번을 돌리는데, for문 안에 있는 이벤트리스너 내부 코드는 '클릭' 이벤트 발생시 실행됨
나중에 버튼을 클릭하면 내부 코드가 실행되는데 모달창들[i]에서 i값을 숫자로 채우려고 하면 Hoisting으로 인해 이미 for문이 다 돌아간 후 값인 var i = 3으로 할당되어있다
즉, for문이 도는 시점과 이벤트리스너 내부 코드가 실행되는 시점이 달라서 에러가 남
💡 해결방법
var 버튼들 = document.querySelectorAll('button');
var 모달창들 = document.querySelectorAll('div');
for (let i = 0; i < 3; i++){
버튼들[i].addEventListener('click', function(){
모달창들[i].style.display = 'block'
});
}
let 변수를 가까이 하자
좋은 글 감사합니다. 자주 올게요 :)