호이스팅 (Hoisting)
: 함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위(함수 블록{})의 최상단에 선언하는 것을 의미
- JavaScript 함수는 실행되기 전 함수 내에 필요한 변수값을 모두 모아 유효 범위의 최상단에 선언
호이스팅 절차
1. JavaScript parser가 함수 실행 전 해당 함수를 한번 훑음
2. 함수 안에 존재하는 변수/함수 선언에 대한 정보를 기억하고 있다가 실행
※ 실제로 코드가 위로 끌어올려지는 것이 아니라, JavaScript parser가 내부적으로 끌어올려서 처리
※ 실제 메모리 변화가 X
호이스팅의 대상 - var 변수 선언과 함수 선언문
- 할당은 끌어올려지지 않음
- let/const 변수 선언과 함수 표현식에서는 호이스팅 발생 X
※ 함수 표현식
- 변수에 할당된 함수 표현식은 변수의 scope 규칙을 따름
- 선언과 할당의 분리가 발생
간단한 예시 (var 변수 vs let/const 변수)
var myname; // [Hoisting O] 변수 선언
myname = "HEEE"; // 할당
let myname2 = "HEEE2"; // [Hoisting X]
간단한 예시 (함수 선언문 vs 함수 표현식)
var foo2; // [Hoisting O] 변수 선언
function foo() { // [Hoisting O] 함수 선언문
console.log("hello");
}
foo();
foo2(); // ERROR 발생
foo2 = function() {
console.log("hello2");
}
함수 선언문과 함수 표현식에서의 호이스팅
1. 함수 선언문에서 호이스팅
함수선언문은 코드를 구현한 위치에 관계없이 자바스크립트의 특징인 호이스팅에 따라 브라우저가 자바스크립트를 해석할 때 맨 위로 끌어 올려짐.
/* 정상 출력 */
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으로 인식하기 때문에 오류 발생 X
2. 함수 표현식에서 호이스팅
- 함수표현식은 함수선언문과 달리 선언과 호출 순서에 따라서 정상적으로 함수가 실행되지 않을 수 있음
함수표현식의 선언이 호출보다 위에 있는 경우 - 정상 출력
/* 정상 */
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"
함수표현식의 선언이 호출보다 아래에 있는 경우 (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
Q. printName에서 “inner is not defined” 이라고 오류가 나오지 않고, “inner is not a function”이라는 TypeError가 나오는 이유?
A. printName이 실행되는 순간, (Hoisting에 의해) inner는 ‘undefined’으로 지정되기 때문
- inner가 undefined라는 것은 즉, 아직은 함수로 인식이 되지 않고 있다는 것을 의미
함수표현식의 선언이 호출보다 아래에 있는 경우 (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
inner에 대한 선언이 되어있지 않기 때문에 이때는 “inner is not defined” 오류가 발생
함수표현식보다 함수선언문을 더 자주 사용하지만, 어떤 코딩컨벤션에서는 함수표현식을 권장
즉, 어떤 컨벤션을 갖던지 한가지만 정해서 사용하는 게 좋음
호이스팅 우선순위
1. 같은 이름의 var 변수 선언과 함수 선언에서의 호이스팅
- 변수선언이 함수 선언보다 우선 순위가 높다.
예제)
var myName = "hi";
function myName() {
console.log("yuddomack");
}
function yourName() {
console.log("everyone");
}
var yourName = "bye";
console.log(typeof myName);
console.log(typeof yourName);
/** --- JS Parser 내부의 호이스팅(Hoisting)의 결과 --- */
// 1. [Hoisting] 변수값 선언
var myName;
var yourName;
// 2. [Hoisting] 함수선언문
function myName() {
console.log("yuddomack");
}
function yourName() {
console.log("everyone");
}
// 3. 변수값 할당
myName = "hi";
yourName = "bye";
console.log(typeof myName); // > "string"
console.log(typeof yourName); // > "string"
2. 값이 할당되어 있지 않은 변수와 값이 할당되어 있는 변수에서의 호이스팅
var myName = "Heee"; // 값 할당
var yourName; // 값 할당 X
function myName() { // 같은 이름의 함수 선언
console.log("myName Function");
}
function yourName() { // 같은 이름의 함수 선언
console.log("yourName Function");
}
console.log(typeof myName); // > "string"
console.log(typeof yourName); // > "function"
- 값이 할당되어 있지 않은 변수의 경우, 함수선언문이 변수를 덮어씀
- 값이 할당되어 있는 변수의 경우, 변수가 함수선언문을 덮어씀
호이스팅 사용 시 주의사항
- 코드의 가독성과 유지보수를 위해 호이스팅이 일어나지 않도록 한다
-- let과 const 사용
-- 함수와 변수를 가급적 코드 상단부에서 선언하면, 호이스팅으로 인한 scope 꼬임 현상 방지
출처
'Programming > JavaScript & TypeScript' 카테고리의 다른 글
npm install 시 npm ERR! code EINTEGRITY 에러 해결 방법 (0) | 2020.09.22 |
---|---|
[Angular5] translate 현재 사용중인 언어 가져오기 (0) | 2020.09.22 |
var VS let VS const 의 차이 (0) | 2020.09.14 |
ECMAScript란? (0) | 2020.09.14 |
[Angular5] translate 번역 값이 안나오고 번역 키가 대신 나오는 현상 해결 (0) | 2020.09.11 |