변수 선언 키워드인 var에 대한 아래 설명을 보고 궁금해서 공부한 내용을 작성합니다.
" var : 함수 스코프를 가지며, 호이스팅(hoisting)으로 인해 변수가 선언되기 이전에도 접근할 수 있습니다. "
1. 스코프
스코프 : 유효한 참조 범위
ex) 함수내부에 선언된 변수가, 함수 내부에서만 참조가 가능하다면 >> 해당 변수의 스코프는 함수 내부
- 함수 내부에서 var로 선언된 변수는 지역 변수의 스코프를 가집니다. 하지만 그외에서 var로 선언된 변수는 전역변수의 스코프를 가집니다. (따라서 함수내부가 아닌 if, for 문 내부에서 선언되더라도 전역변수의 스코프를 가집니다.)
- 모든 블록 내부에서 let과 const로 선언된 변수는 다 지역변수의 스코프를 가집니다. (if, for문 등에서도)
2. 호이스팅
호이스팅 : 말 그대로 끌어올려진다는 의미를 가집니다.
JavaScript에서 호이스팅(hoisting)이란, 인터프리터가 변수와 함수의 선언 전에 메모리 공간을 미리 할당하는 것을 의미합니다.
- 미리할당 한다는 것 = 코드가 맨위로 올라간다 = 호이스팅 된다. 저는 우선 이렇게 이해하고 있습니다.
- 이때, 호이스팅 되는 범위는 해당 함수나 변수의 스코프의 상단 입니다.
- JavaScript는 초기화를 제외한 선언만 호이스팅합니다. (예외로 var 선언 시 undefined, 그 외에는 초기화하지 않음)
- 변수,함수 둘다 호이스팅시 변수를 더위로 위치시킨다.
2-1. 변수 호이스팅
자세히는, 자바스크립트에서는 코드실행 전 자바스크립트 엔진이 ‘코드 평가 과정’을 거칩니다.
‘코드 평가 과정’ 에서 변수 선언을 미리 실행해 두기 때문에, 뒤에 선언된 변수도 앞의 코드에서 참조할 수 있게 됩니다.
그런데, var로 선언한 변수의 경우 호이스팅 시 undefined로 변수를 초기화합니다.
반면 let과 const로 선언한 변수의 경우 호이스팅 시 변수를 초기화하지 않습니다.
이로 인해 var 키워드로 선언된 변수가 호이스팅 될 경우 특이점이 발생합니다.
var 호이스팅
console.log(a); // undefined 출력
var a = 10;
ReferenceError 가 발생하지 않고 undefined 가 나오는 이유는 호이스팅이 발생했기 때문이고 즉, 위 코드는 아래와 같은 의미를 지닙니다. 이 과정을 코드로 표현하면 아래와 같은 의미를 지닙니다.
var a = undefined;
console.log(a); // undefined 출력
var a = 10;
var선언이 함수 내부에서 이루어져 지역변수의 스코프를 가지게 될 때 발생하는 호이스팅 케이스도 알아보겠습니다.
var x = 'outer scope';
(function() {
console.log(x); // outer scope 출력
}());
// 코드에서 사용한 구문은 IIFE(Immediately-invoked function expression: 즉시 작동하는 함수식)라는 구문입니다.
// "이 안에 들어있는 코드를 바로 실행해라" 라는 표현으로 이해하시면 되겠습니다.
위 코드는 정상적으로 전역변수 x 를 함수 내부에서 사용 하기때문에 'outer scope'를 출력합니다.
var x = 'outer scope';
(function() {
console.log(x); // 전역변수인 x가 있지만 undefined를 출력합니다.
var x = 'inner scope';
}());
위 코드에서는, 변수 x는(1줄에 전역변수가 있음에도) undefined 이 출력됩니다.
4번째 줄의 변수 x는 함수레벨 스코프로 함수내부에서 선언되었고, 지역변수로써 인정받습니다. 그래서, 참조 가능한 범위인 스코프는 함수 내부인 { } 속 입니다. 이 때 호이스팅이 발생합니다.
그래서 위 코드는 아래 코드와 같은 의미를 지닙니다.
var x = 'outer scope';
(function() {
var x = undefined;
console.log(x); // undefined 출력
x = 'inner scope';
}());
let / const 호이스팅
이부분은 이해가 되는 부분을 정확히 설명 하기힘들어 결론만 작성 합니다.
- 호이스팅이 발생한다.
- 하지만, const/let은 TDZ에 영향을 받아 선언 전에 변수를 사용하는것을 허용하지 않습니다. 그렇기 때문에 호이스팅이 발생하지 않는 것처럼 보입니다.
** 변수 스코프의 맨 위에서 변수의 초기화 완료 시점까지의 변수는 "시간상 사각지대"(Temporal Dead Zone, TDZ)에 들어간 변수라고 표현합니다.
3-1. 함수 호이스팅
- 함수 선언식 : 호이스팅이 발생합니다.
- 함수 표현식 : 호이스팅이 발생하지 않습니다.
함수 선언식 호이스팅
console.log(declarationFunc('함수선언식')); // "함수 선언식" 출력
// 함수 선언식 사용
function declarationFunc(name) {
return name;
}
위 코드는 호출 -> 선언 순으로 작성 되었지만, 호이스팅이 발생해서 정상적으로 함수를 호출 합니다. (즉, 실제동작은 선언 -> 호출 과 같습니다.)
함수 표현식 호이스팅
console.log(expressionFunc('함수표현식')); // TypeError: expressionFunc is not a function 출력
// 함수 표현식 사용
var expressionFunc = function (name) {
return name;
}
위 코드에서, var키워드 때문에 변수 호이스팅이 이루어지면서 expressionFunc이 초기화되고 TypeError가 발생합니다.
var가 아닌 let / const 키워드 사용해서 함수 표현식을 작성하면 호이스팅이 일어나지 않아 ReferenceError 발생합니다.
요약
- 함수선언식 사용시 호이스팅이 이루어 지는것을 인식하자.
- var는 사실 사용을 거의하지 않는다고 합니다.
- 변수의 호이스팅은 var / let / const 에서 모두 발생하지만, let과 const 는 TDZ의 영향을 받아 호이스팅 발생x 처럼 보인다.
참고 사이트.
https://tecoble.techcourse.co.kr/post/2021-04-25-hoisting/
'JavaScript' 카테고리의 다른 글
[JavaScript] sort() (0) | 2024.01.30 |
---|---|
[JavaScript] 스코프와 비동기적 실행,렉시컬 환경, 클로저 (0) | 2023.12.13 |
[JavaScript]객체의 메서드에 this를 쓸때 헷갈리는 동작 (0) | 2023.08.29 |