관리 메뉴

공부기록용

CS_호이스팅 본문

💡깨달음💡/CS

CS_호이스팅

과부하가즈아 2023. 6. 18. 18:53

호이스팅

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

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

  • 자바스크립트 Parser가 함수 실행 전 해당 함수를 한 번 훑는다.
  • 함수 안에 존재하는 변수/함수선언에 대한 정보를 기억하고 있다가 실행시킨다.
  • 유효 범위: 함수 블록 {} 안에서 유효

즉, 함수 내에서 아래쪽에 존재하는 내용 중 필요한 값들을 끌어올리는 것이다.

(코드를 실행하기 전 변수선언/함수선언을 해당 스코프의 최상단으로 끌어올리는 것이 아니며, 끌어 올려진 것 같은 현상을 말한다. 자바스크립트 Parser 내부적으로 끌어올려서 처리하는 것이다. 실제 메모리에서는 변화는 없다.)

이 호이스팅이라는 용어를 선언이 코드 실행 보다 먼저 메모리에 저장되는 과정으로 인한 현상을 호이스팅이라고 부른다는 것으로 이해하면 되겠다.


변수 생성 단계

자바스크립트 엔진에서 변수는 선언 → 초기화 → 할당을 거쳐 변수가 생성된다.

1단계: 선언 단계(Declaration phase)_예) var myValue

  • 변수를 실행 컨텍스트의 변수 객체에 등록한다.
  • 이 변수 객체는 스코프가 참조하는 대상이 된다.

2단계: 초기화 단계(Initialization phase)_예) myValue = 100

  • 변수 객체에 등록된 변수를 위한 공간을 메모리에 확보한다.
  • 이 단계에서 변수는 undefined로 초기화 된다.

3단계: 할당 단계(Assignment phase)_ 예) alert(myValue)

  • undefined로 초기화된 변수에 실제 값을 할당한다

호이스팅의 대상

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

console.log(a); // undefined
var a = "A"; // var 변수 

/* 호이스팅 된 코드 */
var a; 
console.log(a);
a = "A";
var a를 상단으로 호이스팅했기 때문에 변수 선언 전에 console.log로 출력을 해도 에러가 발생하지 않고, undefined가 출력된다. 모든 선언(function, var, let, const, class)은 JavaScript에서 호이스팅되며, var 선언은 undefined로 초기화되지만 let 및 const 선언은 초기화되지 않은 Temporal Dead Zone 상태로 유지된다.

자바 스크립트 엔진은 코드를 실행하기 전에 실행 컨텍스트에 등록된 변수 객체에 접근할 수 있다.

  • var의 경우 변수 선언&초기화가 함께 진행되므로, 변수 객체 등록과 동시에 메모리 공간도 할당 받는다.
    • 그렇기 때문에 메모리를 할당받은 상태이므로 호이스팅시 메모리 참조를 통해 변수 접근이 가능하다.
  • let의 경우, 선언과 초기화를 각각 진행한다.
    • 선언 단계에서 실행 컨텍스트에 등록은 했지만, 메모리를 할당받지 못해 접근이 불가능한 상태이다. 결국, 메모리를 할당받지 못해 참조할 메모리가 없으므로 ReferenceError가 발생한다.
    • 변수는 선언된 위치에서 초기화하기 전까지 TDZ 안에 들어간다.(그래서 선언하기 전에 변수를 사용할 수 없음)
      • TDZ(Temporal Dead Zone) : 일시적인 사각지대라는 뜻 스코프의 시작 지점부터 초기화 시작 지점까지의 구간을 말한다.
  • 모든 선언(function, var, let, const 및 class)은 JavaScript에서 호이스팅되며, var 선언은 undefined로 초기화되지만 let 및 const 선언은 초기화되지 않은 상태로 유지된다. (선언에는 호이스팅이 발생하지만 초기화는 호이스팅 되지 않는다는 의미)

호이스팅 법칙

1. 매개변수 및 변수는 선언부를 호이스팅한다.

2. 함수 선언은 전체를 호이스팅한다.

함수 호이스팅
함수의 선언 역시 호이스팅의 대상으로 스코프 내에서 어떤 위치에서 함수 선언을 하든지 호출할 수 있다.

<함수 선언식>
sayName();

function sayName(){
  console.log('yuddomack');
}​


function sayName(){
  console.log('yuddomack');
}

sayName();​

함수 선언 역시 최상단으로 끌어올려지기 때문에 sayName()을 먼저 호출하고 함수 정의를 이후에 하여도 정상적으로 작동함



<함수 표현식>

sayName();

var sayName = function(){
  console.log('yuddomack');
}

var sayName;

sayName();

sayName = function(){
  console.log('yuddomack');
}

var sayName은 변수이기 때문에 '선언과 할당'의 분리가 발생한다. sayName이 선언되고 sayName()이 호출되지만 거기엔 아무것도 없습니다. 그 이후에 sayName에 함수가 정의되는 것


변수 '할당'이 함수 선언보다 우선 순위이고, 함수 선언이 변수 선언보다 우선 순위이다.(변수 할당>함수 선언> 변수 선언)
함수 선언문과 변수 할당문이 존재할경우, 변수 a선언 -> 함수 a선언 -> a에 값할당 순으로 실행된다.

var myName = "hi";

function myName() {
  console.log("yuddomack");
}
function yourName() {
  console.log("everyone");
}

var yourName = "bye";

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


var myName;
var yourName;
function myName() {
  console.log("yuddomack");
}
function yourName() {
  console.log("everyone");
}

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

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

변수가 선언되고, 함수가 할당되지만 다시 String 값이 들어가게 됩니다.

 

💫

함수 선언문을 이용해서 코드를 작성하게된다면 그 함수 선언문이 나도 인지하지 못하는 사이에 호이스팅에 의해 위로 끌어올려져서 코드 전체에 영향을 끼치게 될 수 있다.

반면 표현식으로 작성한 경우에는 이 같은 위험과 무지에서 벗어날 수 있으므로 복잡하거나 전역 공간에서 이루어지는 코드 협업일수록 함수 표현식을 활용하는 습관이 중요하다.

Comments