👍 목표
- 호이스팅(Hoisting)이란 무엇인지 이해합니다.
- 함수 선언문과 함수 표현식에서의 호이스팅 차이를 이해합니다.
- let / const와 var 변수 선언에서의 호이스팅 예시 차이를 이해합니다.
- 같은 이름의 var 변수 선언과 함수 선언에서의 호이스팅에 대해 이해합니다.
👏호이스팅(Hoisting)의 개념
함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언하는 것을 말합니다. 단 선언에 대한 부분만 끌어올려지고 값의 할당은 끌어올려지지 않습니다.
✔ 호이스팅이란
자바스크립트 Parser는 현재 실행될 컨텍스트의 대상 코드 내에 어떤 식별자들이 있는지를 먼저 수집합니다.
때문에, 변수를 인식할 때 식별자를 모두 모아서 유효 범위의 최상단에 선언합니다. 단 값의 할당 과정은 원래 자리에 순서대로 남겨둡니다. 이를 호이스팅이라고 합니다.
즉, 함수 내에서 아래쪽에 존재하는 내용 중 필요한 값들을 끌어올리는데 실제로 코드가 끌어올려지는 건 아니며, 자바스크립트 Parser 내부적으로 끌어올려서 처리하는 것으로 메모리에서는 변화가 없습니다.
✔ 호이스팅의 대상
var 변수 선언과 함수 선언문에서만 호이스팅이 일어나며 할당은 끌어올려지지 않습니다.
let/const 변수 선언과 함수 표현식에서는 호이스팅이 발생하지 않습니다.
console.log(a); // undefiend
// 함수선언문
function foo() {
console.log("hello");
}
// 함수표현식
var foo2 = function() {
console.log("hello2");
}
var a = '호이스팅 테스트';
console.log(a); // 호이스팅 테스트
호이스팅은 함수 선언문과 함수 표현식에서 서로 다르게 동작하기 때문에 주의해야 합니다. 변수에 할당된 함수 표현식은 끌어올려지지 않기 때문에 이때는 변수의 스코프 규칙을 그대로 따릅니다.
✔ 함수 선언문과 함수 표현식에서의 호이스팅
- 함수 선언문에서의 호이스팅
함수 선언문은 코드를 구현한 위치와 관계없이 자바스크립트의 특징인 호이스팅에 따라 브라우저가 자바스크립트를 해석할 때 맨 위로 끌어올려집니다.
/* 정상 출력 */
function printName(firstname) { // 함수선언문
var result = inner(); // "선언 및 할당"
console.log(typeof inner); // > "function"
console.log("name is " + result); // > "name is inner value"
function inner() { // 함수선언문
return "inner value";
}
}
printName(); // 함수 호출
/** --- JS Parser 내부의 호이스팅(Hoisting)의 결과 - 위와 동일 --- */
/* 정상 출력 */
function printName(firstname) {
var result; // [Hoisting] var 변수 "선언"
function inner() { // [Hoisting] 함수선언문
return "inner value";
}
result = inner(); // "할당"
console.log(typeof inner); // > "function"
console.log("name is " + result); // > "name is inner value"
}
printName();
위의 예제에서는 함수 선언문이 아래에 있어도 printName 함수 내에서 inner를 function으로 인식하기 때문에 오류가 발생하지 않습니다.
- 함수 표현식에서의 호이스팅
함수 표현식은 함수 선언문과 달리 선언과 호출 순서에 따라서 정상적으로 함수가 실행되지 않을 수 있습니다. 함수 표현식에서는 선언과 할당의 분리가 발생합니다.
1) 함수 표현식의 선언이 호출보다 위에 있는 경우 - 정상 출력
/* 정상 */
function printName(firstname) { // 함수선언문
var inner = function() { // 함수표현식
return "inner value";
}
var result = inner(); // 함수 "호출"
console.log("name is " + result);
}
printName(); // > "name is inner value"
/* 정상 */
/** --- JS Parser 내부의 호이스팅(Hoisting)의 결과 - 위와 동일 --- */
function printName(firstname) {
var inner; // [Hoisting] 함수표현식의 변수값 "선언"
var result; // [Hoisting] var 변수값 "선언"
inner = function() { // 함수표현식 "할당"
return "inner value";
}
result = inner(); // 함수 "호출"
console.log("name is " + result);
}
printName(); // > "name is inner value"
2) 함수표현식의 선언이 호출보다 아래에 있는 경우 (var 변수에 할당) - TypeError
/* 오류 */
function printName(firstname) { // 함수선언문
console.log(inner); // > "undefined": 선언은 되어 있지만 값이 할당되어있지 않은 경우
var result = inner(); // ERROR!!
console.log("name is " + result);
var inner = function() { // 함수표현식
return "inner value";
}
}
printName(); // > TypeError: inner is not a function
/** --- JS Parser 내부의 호이스팅(Hoisting)의 결과 --- */
/* 오류 */
function printName(firstname) {
var inner; // [Hoisting] 함수표현식의 변수값 "선언"
console.log(inner); // > "undefined"
var result = inner(); // ERROR!!
console.log("name is " + result);
inner = function() {
return "inner value";
}
}
printName(); // > TypeError: inner is not a function
printName에서 “inner is not defined”이라고 오류가 나오지 않고, “inner is not a function”이라는 TypeError가 나오는 이유는 printName이 실행되는 순간 (Hoisting에 의해) inner는 ‘undefined’으로 지정되기 때문이며 inner가 undefined라는 것은 즉, 아직은 함수로 인식이 되지 않고 있다는 것을 의미합니다.
3) 함수 표현식의 선언이 호출보다 아래에 있는 경우 (const/let 변수에 할당) - ReferenceError
/* 오류 */
function printName(firstname) { // 함수선언문
console.log(inner); // ERROR!!
let result = inner();
console.log("name is " + result);
let inner = function() { // 함수표현식
return "inner value";
}
}
printName(); // > ReferenceError: inner is not defined
let/const의 경우, 호이스팅이 일어나지 않기 때문에 위의 예시 그대로 이해하면 됩니다.
console.log(inner);
에서 inner에 대한 선언이 되어있지 않기 때문에 이때는 “inner is not defined” 오류가 발생합니다.
👍같이 읽어보면 좋을 글
출처 : https://gmlwjd9405.github.io/2019/04/22/javascript-hoisting.html
'IT > JavsScript' 카테고리의 다른 글
Lodash 활용법 알아보기 (0) | 2022.06.28 |
---|---|
반복문 'for', 'forEach', 'map' 사용법과 차이점 (1) | 2022.06.23 |
객체 복사 ( Object.assign (), $.extend() ) (0) | 2022.06.13 |
클로저 이번에 재대로 이해하기 (0) | 2022.06.02 |
[JavaScript] 문자열 특정 문자 위치 찾기 (indexOf, search) (0) | 2022.05.26 |
제 블로그의 모든 글은 제가 직접 작성 하고 다른 글을 참고할 때는 이전 글보다 읽기 편하게 수정해서 작성하고 있습니다. 커피 한잔 사먹고 더 열심히 좋은글로 보답하겠습니다.
오늘도 제 블로그에 와 주셔서 감사합니다. :)