호이스팅(Hoisting) 이해하기

Instant Coffee·2021년 5월 19일
0

JS 문법

목록 보기
3/9
post-thumbnail
post-custom-banner

호이스팅(Hoisting)의 개념

함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언하는 것을 말한다.

자바스크립트 함수는 실행되기 전에 함수 안에 필요한 변수값들을 모두 모아서 유효 범위의 최상단에 선언한다.

자바스크립트 Parser가 함수 실행 전 해당 함수를 한 번 훑는다.

호이스팅의 대상

var 변수 선언과 함수선언문에서만 호이스팅이 일어난다.

  • var 변수/함수의 선언만 위로 끌어 올려지며, 할당은 끌어 올려지지 않는다.
  • let/const 변수 선언과 함수표현식에서는 호이스팅이 발생하지 않는다.

*호이스팅은 함수선언문과 함수표현식에서 서로 다르게 동작하기 때문에 주의해야 한다.

foo();
foo2();
function foo(){
	console.log("hello")
}
var foo2 = function(){
	console.log("hello2");
}
//hello
//TypeError: foo2 is not a function

*변수에 할당된 함수표현식은 끌어 올려지지 않기 때문에 이때는 변수의 스코프 규칙을 그대로 따른다.

var foo2; // 호이스팅. 함수표현식의 변수값 "선언"

function foo() {
	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(); // 함수 호출

위 함수의 JS Parser 호이스팅 결과.

  • 함수선언문이 아래에 있어도 printName 함수 내에서 inner를 function으로 인식하기 때문에 오류가 발생하지 않는다.
function printName(firstName){
	var result; // 호이스팅. var 변수 "선언"
  
  	function inner() { // 호이스팅. 함수선언문
		return "inner value";
	}
  
  	result = inner(); // 할당
  	console.log(typeof inner); // "function"
  	console.log("name is" + result); // "name is inner value"
}
printName();

함수표현식에서의 호이스팅

  • 함수 표현식은 함수선언문과 달리 선언과 호출 순서에 따라서 정상적으로 함수가 실행되지 않을 수 있다.
    -> 함수 표현식에서는 선언과 할당의 분리가 발생한다.
  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 내부 호이스팅 결과는 같다.
function printName(firstname){
	var inner;
  	var result;
  
  	inner = function(){
		return "inner value";
	}
  
  	result = inner();
  	console.log("name is " + result);
}
printName();
  1. 함수표현식의 선언이 호출보다 아래에 있는 경우 (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

호이스팅 결과

function printName(firstname){
	var inner; // 호이스팅. 함수 표현식의 변수값 "선언"
  	
  	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이 실행되는 순간 (호이스팅) inner는 "undefined"로 지정되기 때문에. inner가 undefined라는 것은 즉, 아직은 함수로 인식되지 않고 있다는 것을 의미한다.
  1. 함수 표현식의 선언이 호출보다 아래에 있는 경우. (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(); // RefereneceError : inner is not defined
  • let/const의 경우 호이스팅이 일어나지 않는다.
  • console.log(inner); 에서 inner에 대한 선언이 되어있지 않기 때문에, 이때는 "inner is not defined" 오류를 발생한다.

호이스팅 우선순위

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

  • 변수 선언이 함수 선언보다 위로 끌어올려진다.
var myname = "marvel";

function myName(){
	console.log("superman");
}
function yourName(){
	console.log("batman");
}

var yourName() = "ironman";

console.log(typeof myName);
console.log(typeof yourName);

호이스팅 결과.

// 1. 호이스팅 변수값 선언.
var myName;
var yourName;
// 2. 호이스팅 함수선언문 
function myName(){
	console.log("superman");
}
function yourName(){
	console.log("batman");
}
// 3. 변수값 할당.
myName = "marvel";
yourName = "ironman";

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

값이 할당되어 있지 않은 변수와 값이 할당되어 있는 변수에서의 호이스팅.

var myName = "ironman"; // 값 할당
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를 사용하자.
profile
DevelDope 不狂不及 성장하는 개발로그
post-custom-banner

0개의 댓글