함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언하는 것을 말한다.
- 자바스크립트 Parser가 함수 실행 전 해당 함수를 한 번 훑는다.
- 함수 안에 존재하는 변수/함수선언에 대한 정보를 기억하고 있다가 실행시킨다.
- 유효 범위: 함수 블록 {} 안에서 유효
- 실제로 코드가 끌어올려지는 건 아니며, 자바스크립트 Parser 내부적으로 끌어올려서 처리하는 것이다.
- 실제 메모리에서는 변화가 없다.
- var 변수/함수의 선언만 위로 끌어 올려지며, 할당은 끌어 올려지지 않는다.
- let/const 변수 선언과 함수 표현식에서는 호이스팅이 발생하지 않는다.
console.log('hello');
var myname = 'jinhyeok'; // var 변수
let myname2 = 'jinhyeok2'; // let 변수
var myname; // Hoisting 발생 o
console.log('hello');
myname = 'jinhyeok'; // "할당"
let myname2 = 'jinhyeok2'; // Hoisting 발생 x
foo();
foo2();
function foo() { // 함수 선언식
console.log('hello');
}
var foo2 = function () { // 함수 표현식
console.log('hello2');
}
var foo2; // Hoisting 함수표현식의 변수값 선언
function foo() { // Hoisting 함수 선언식
console.log('hello');
}
foo();
foo2(); // Error
foo2 = function() {
console.log('hello2');
}
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(); // 함수 호출
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();
function printName(firstname) { // 함수 선언식
var inner = function () { // 함수 표현식
return "inner value";
}
var result = inner(); // 함수 "호출"
console.log("name is "+result);
}
printName(); // "name is inner value"
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"
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
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
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
- 즉, 어떤 컨벤션을 갖던지 한가지만 정해서 사용하는 게 좋다.
같은 이름의 var 변수 선언과 함수 선언식에서의 호이스팅
var myName = "hi";
function myName() {
console.log('jinhyeok');
}
function yourName() {
console.log('everyone');
}
var yourName = "bye";
console.log(typeof myName);
console.log(typeof yourName);
var myName; // Hoisting 변수값 선언
var yourName;
function myName() { // Hoisting 함수 선언식
console.log("jinhyeok");
}
function yourName() {
console.log("everyone");
}
myName = "hi"; // 변수값 할당
yourName = "bye";
console.log(typeof myName);
console.log(typeof yourName);
var myName = "jinhyeok"; // 값 할당 o
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를 사용한다.
var를 쓰면 혼란스럽고 쓸모없는 코드가 생길 수 있다. 그럼 왜 var와 호이스팅을 이해해야 할까 ?
- ES6를 어디에서든 쓸 수 있으려면 아직 시간이 더 필요하므로 ES5로 트랜스컴파일을 해야한다.
- 따라서 아직은 var가 어떻게 동작하는지 이해하고 있어야 한다.