호이스팅 (Hoisting)

예동·2023년 8월 18일

노트

목록 보기
7/10

호이스팅(Hoisting)

함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언하는 것
함수 표현식의 익명함수는 호이스팅의 영향을 받지 않는 반면, 함수 선언식의 기명함수는 호이스팅의 영향을 받음

  • JavaScript Parser 실행 순서

      1. Parser가 함수 실행 전 해당 함수를 한 번 훑으며 점검
      1. 함수 안에 존재하는 변수나 함수 선언문에 대한 정보를 기억
      1. 2번에 해당하는 변수나 선언문을 함수 유효 범위의 최상단에 선언
  • 주의사항

    • 유효범위인 함수 블록 {...} 안에서만 유효
    • 실제 코드가 끌어올려지는 것은 아니며 Parser 내부적으로 끌어올려 처리되는 과정
    • 실제 메모리에는 변화 없음
  • 호이스팅 대상

    • var로 선언된 변수var 선언함수만 호이스팅이 발생함
    • var 변수와 var 선언함수의 선언부만 위로 끌어올려지며, 할당부 및 할당된 값은 끌어올려지지 않음
    • let과 const 변수let과 const 선언함수는 호이스팅이 발생하지 않음
  • Tip

    • 코드의 가독성과 유지보수를 위해 최대한 호이스팅이 일어나지 않도록 주의
    • 이를 위해서 함수와 변수를 가급적 코드 상단부에 선언하고, var 대신 let과 const를 사용해야 함


Parser 실행 예시

변수 선언 예시1

  • 실제 코드
console.log("hello");			// >> hello
var myname = "yz"; 				// var 변수 
let myname2 = "lumpyspaceyz"; 	// let 변수 
  • JS Parser 내부의 호이스팅(Hoisting)의 결과
var myname; 					// var 변수의 선언부

// ----------------------------	// Hoisting으로 인해 끌어올려짐

console.log("hello");			// >> hello
myname = "yz";					// var 변수의 할당부
let myname2 = "lumpyspaceyz"; 	// let 변수는 호이스팅 되지 않음

변수 선언 예시2

  • 실제 코드
console.log(name); 				// >> undefined
console.log(name2); 			// >> Error: Uncaught ReferenceError: name2 is not defined
var name = "yz";				// var 변수
let name2 = "lumpyspaceyz";		// let 변수
  • JS Parser 내부의 호이스팅(Hoisting)의 결과
var name;						// var 변수의 선언부

// ----------------------------	// Hoisting으로 인해 끌어올려짐

console.log(name); 				// >> undefined
console.log(name2); 			// >> Error: Uncaught ReferenceError: name2 is not defined
name2 = "yz";					// var 변수의 할당부
let name2 = "lumpyspaceyz";		// let 변수는 호이스팅 되지 않음

🙇🏻‍♀️ var 변수는 호이스팅으로 인해 우선적으로 유효범위 최상단에 선언되고 후에 할당되지만
let 변수는 호이스팅이 적용되지 않음


함수 선언식 예시1 👉🏻 ERROR

  • 실제 코드
foo();
foo2();

function foo() { 				// 함수 선언식
	console.log("hello");		// >> hello
}

var foo2 = function() { 		// var 변수의 함수 표현식
	console.log("hello2");		// >> ERROR : Uncaught TypeError: foo2 is not a function
}
  • JS Parser 내부의 호이스팅(Hoisting)의 결과
var foo2;						// var 변수의 함수 표현식의 선언부

function foo() { 				// 함수 선언식
	console.log("hello");		
}

// ----------------------------	// Hoisting으로 인해 끌어올려짐

foo(); 							// >> hello
foo2(); 						// >> ERROR : Uncaught TypeError: foo2 is not a function

foo2 = function() { 			// var 변수의 함수 표현식의 할당부
	console.log("hello2");
}

함수 선언식 예시2

  • 실제 코드
function printName(firstname) { 			// 함수 선언식 
    var result = inner(); 					// var 변수
    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; 							// var 변수의 선언부

    function inner() { 						// 함수 선언식
        return "inner value";
    }
    
// ----------------------------------------	// Hoisting으로 인해 끌어올려짐

    result = inner(); 						// var 변수의 할당부
    console.log(typeof inner); 				// >> function
    console.log("name is " + result); 		// >> name is inner value
}

printName();								// 함수 호출

🙇🏻‍♀️ 호이스팅은 함수 선언문과 함수 표현식에서 서로 다르게 동작하기 때문에 주의
함수 선언식 function foo() {} 은 함수 자체가 호이스팅 됨
함수 표현식 var foo2 = function() {} 은 호이스팅이 일어날 때 foo2 변수 에 대한 선언만 호이스팅 되고, 할당은 후에 됨


함수 표현식 예시1

  • 함수 표현식의 선언부가 호출보다 위에 있는 경우
  • 실제 코드
function printName(firstname) { 			// 함수 선언식
     var inner = function() { 				// var 변수의 함수 표현식 
         return "inner value";
     }
        
     var result = inner(); 					// var 변수
     console.log("name is " + result);		// >> name is inner value
 }

 printName(); 								// 함수 호출
  • JS Parser 내부의 호이스팅(Hoisting)의 결과
function printName(firstname) { 
     var inner; 							// var 변수의 함수 표현식의 선언부
     var result; 							// var 변수의 선언부
     
// ----------------------------------------	// Hoisting으로 인해 끌어올려짐

     inner = function() { 					// var 변수의 함수 표현식의 할당부
         return "inner value";
     }
        
     result = inner(); 						// var 변수의 할당부
     console.log("name is " + result);		// >> name is inner value
 }

 printName(); 								// 함수 호출

함수 표현식 예시2 👉🏻 ERROR

  • 함수 표현식의 선언부가 호출보다 아래에 있는 경우
  • 실제 코드
function printName(firstname) { 			// 함수 선언식
     console.log(inner); 					// >> undefined : 선언은 되어 있지만 값이 할당되어있지 않은 경우
     var result = inner(); 					// var 변수
     										// ERROR : TypeError inner is not a function
     console.log("name is " + result);

     var inner = function() { 				// var 변수의 함수 표현식 
         return "inner value";
     }
 }
 printName(); 								// 함수 호출	
  • JS Parser 내부의 호이스팅(Hoisting)의 결과
function printName(firstname) { 
     var inner; 							// var 변수의 함수 표현식의 선언부
     var result;							// var 변수의 선언부
     
// ----------------------------------------	// Hoisting으로 인해 끌어올려짐

     console.log(inner); 					// >> undefined : 선언은 되어 있지만 값이 할당되어있지 않은 경우
     result = inner(); 						// var 변수의 할당부
     										// ERROR : TypeError inner is not a function
     console.log("name is " + result);

     inner = function() { 
         return "inner value";
     }
 }
 printName(); 								// 함수 호출

🙇🏻‍♀️ ERROR에서 inner is not defined 오류가 아닌 inner is not a function 오류가 나는 이유는?
👉🏻 호이스팅에 인해 inner은 function이 할당되기 전에 선언되기 때문에 inner는 먼저 undefined로 지정됨
inner에 undefined가 지정되었다는 것은 즉, 아직은 함수가 아니라는 의미



호이스팅 우선순위

같은 이름의 var 변수 선언과 함수 선언식에서의 호이스팅1

  • 실제 코드
var myName = "hi";							// var 변수 myName

function myName() {						// 함수 선언식 myName
	console.log("lumpyspaceyz");
}
function yourName() {					// 함수 선언식 yourName
	console.log("everyone");
}

var yourName = "bye";						// var 변수 yourName

console.log(typeof myName);					// >> string
console.log(typeof yourName);				// >> string
  • JS Parser 내부의 호이스팅(Hoisting)의 결과
var myName; 								// var 변수의 선언부
var yourName; 								// var 변수의 선언부

function myName() {							// 함수 선언식
	console.log("yuddomack");
}											// 함수 선언식
function yourName() {
	console.log("everyone");
}

// ----------------------------------------	// Hoisting으로 인해 끌어올려짐

myName = "hi";								// var 변수의 할당부
yourName = "bye";							// var 변수의 할당부

console.log(typeof myName); 				// >> string
console.log(typeof yourName); 				// >> string

🙇🏻‍♀️ var 변수 선언이 함수 선언식보다 먼저 호이스팅 됨

같은 이름의 var 변수 선언과 함수 선언식에서의 호이스팅2 - 값의 할당 여부

  • 변수에 값이 할당되어 있지 않은 경우
  • 실제 코드
var myName = "hi";							// 값이 할당된 var 변수 myName
var yourName;								// 값이 할당되지 않은 var 변수 yourName 

function myName() {						// 함수 선언식 myName
	console.log("lumpyspaceyz");
}
function yourName() {					// 함수 선언식 yourName
	console.log("everyone");
}

console.log(typeof myName);					// >> string
console.log(typeof yourName);				// >> function
  • JS Parser 내부의 호이스팅(Hoisting)의 결과
var myName; 							// 값이 할당된 var 변수의 선언부 

function myName() { 					// 함수 선언식 myName
	console.log("myName Function");
}
function yourName() {					// 함수 선언식 yourName
	console.log("yourName Function");
}

// ----------------------------------------	// Hoisting으로 인해 끌어올려짐

myName = "Heee";

console.log(typeof myName); 				// >> string
console.log(typeof yourName);				// >> function

❗️ 값이 할당되어 있지 않은 var 변수 yourName의 경우, 같은 이름의 함수 yourName에 변수가 덮어씌워짐

같은 이름의 var 변수 선언과 함수 선언식에서의 호이스팅3 - 값의 할당 여부

  • 함수에 값이 할당되어 있지 않은 경우
  • 실제 코드
var myName = "hi";							// 값이 할당된 var 변수 myName
var yourName = "bye";						// 값이 할당되지 않은 var 변수 yourName 

function myName() {							// 값이 할당된 함수 선언식 myName
	console.log("lumpyspaceyz");
}
function yourName() {}						// 값이 할당되지 않은 함수 선언식 yourName

console.log(typeof myName);					// >> string
console.log(typeof yourName);				// >> string
  • JS Parser 내부의 호이스팅(Hoisting)의 결과
var myName;									// 값이 할당된 var 변수의 선언부
var yourName;								// 값이 할당된 var 변수의 선언부 

function myName() {							// 값이 할당된 함수 선언식 myName
	console.log("lumpyspaceyz");
}
    
// ----------------------------------------	// Hoisting으로 인해 끌어올려짐

myName = "hi";
yourName = "bye";

console.log(typeof myName);					// >> string
console.log(typeof yourName);				// >> string

❗️ 값이 할당되지 않은 함수 선언문 yourName의 경우, 같은 이름의 yourName 변수에 함수 선언문이 덮어씌워짐



결론

코드의 가독성유지보수를 위해 가능한 호이스팅이 일어나지 않도록

이를 위해서 함수와 변수를 가급적 코드 상단부에 선언하고, var 대신 let이나 const를 사용한다




[출처] https://velog.io/@franchesca/%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85hoisting%EC%9D%B4%EB%9E%80

0개의 댓글