-05- 인사이드 자바스크립트

mintgranita·2024년 3월 9일

JS101

목록 보기
5/9
post-thumbnail

자바스크립트 엔진

자바스크립트 엔진은 다음과 같이 콜 스택과 힙으로 구성되어있습니다. 힙은 앞서 봤듯이 Reference type변수의 실제 값이 저장되는 곳이고 이 글에서는 콜 스택에 대해서 주로 다루겠습니다.

호출스택 (Call stack)

콜 스택의 역할은 함수의 실행 순서를 정해 주는 것입니다. 스택(stack)이란 말 그대로 쌓는다는 의미입니다. 스택 자료구조는 나중에 들어온 것부터 실행됩니다. (Last In First Out)

let a = 'Hello World!';
function first() {
  console.log('Inside first function');
  second();
  console.log('Again inside first function');
}
function second() {
  console.log('Inside second function');
}
first();
console.log('Inside Global Execution Context');

// 결과
//Inside first function
//Inside second function
//Again inside first function
//Inside Global Execution Context

실행문맥 (Execution context)

실행 문맥이란 자바스크립트 코드가 동작하는 환경을 말합니다. 동작하는 코드를 위한 모든 정보들이 저장되어 있습니다. 정확하게 하나의 글로벌 환경이 있으며 각각의 함수 호출에 대해 함수 실행환경이 생성됩니다. 실행 문맥은 변수 환경(변수의 값? 타입?...), 스코프 체인, this키워드로 구성되어 있습니다.

Global EC: 코드에서 기본적으로 생성되는 코드이며 어떤 함수의 안이 아니라 밖에 형성됩니다.

Function EC: 하나의 함수당 하나의 실행 문맥을 가지고 있습니다 함수 실행 문맥은 함수가 호출될 때 생성됩니다.

스코프 (Scope)

스코프란 어떤 변수가 선언된 환경을 뜻합니다 스코프는 세 종류가 있습니다.

전역스코프: 어떤 함수 혹은 블록의 바깥에서 선언된 변수의 스코프가 전역 스코프입니다. 전역 스코프에서 선언된 변수는 코드의 어디에서나 접근 가능합니다.

// 전역 스코프에서 변수선언
const userName = "Sarah";

function greeting() {
  // 함수 안에서 전역변수에 접근가능함
  console.log(\`Hello ${userName}!\`);
}

greeting();  // "Hello Sarah!"

함수 스코프: 어떤 변수가 함수 내부에서 선언되었을 때 그 변수의 스코프가 함수 스코프입니다. 함수 스코프를 가진 변수들은 함수 블록 내부에서만 접근 가능합니다.

function calcAge(birthyear) {
  // calcAge 험수 스코프 안에서  변수 선언
  const currentYear = 2021;
  const age = currentYear - birthyear;
  return age;
}
calcAge(1975);
// 함수 스코프 바깥에서는 "currentYear" 와"age"에 접근할 수 없음
console.log(currentYear); // ReferenceError: currentYear is not defined
console.log(age); // ReferenceError: age is not defined

블록 스코프(ES6): ES6에서 처음 도입된 스코프로 let이나 const로 변수를 선언하면 블록 스코프를 가집니다 변수들이 블록({ })안에서만 접근 가능하기 때문에 for문이나 if문에서 사용하기 편합니다.

function calcAge(birthyear) {
  const currentYear = 2021;
  const age = currentYear - birthyear;
  if (age <= 60) {
    // Create a variable using "var" inside the block
    var working = true;
    // Create a variable using "const" inside the block
    const message = `Peter is still employed!`;
    console.log(message);
  }
  // "var" 로 선언된 변수는 블록 밖에서도 접근가능
  console.log(working); // true
  // message"는 const로 선언되었기 때문에 스코프 바깥에서 접근할 수 없음.
  console.log(message); // ReferenceError: message is not defined at calcAge
}
calcAge(1975);

스코프는 여러 개 중첩이 가능합니다. 스코프가 겹쳐져 있을 때 안쪽 스코프에서 바깥쪽 스코프에 있는 변수에는 접근이 가능합니다. 하지만 그 반대는 불가능합니다.

스코프 체인은 안쪽 스코프에서 바깥쪽 스코프로만 가능!

// Global variable
const userName = "Peter";

// Outer function
function calcAge(birthyear) {
  const currentYear = 2021;
  const age = currentYear - birthyear;

   // inner block
  if (age <= 60) {
    var working = true;
    const message = \`Peter is still employed!\`;
    console.log(message);
  }

  // inner function
  function yearsToRetire() {
    const retirement = 60 - age;
    console.log(\`${userName} will be retired in ${retirement} years!\`);
  }

  yearsToRetire();
}

calcAge(1975);

안쪽 스코프에서 어떤 변수가 필요한데 없다면 필요한 변수를 찾아 바깥 스코프에 있는 변수를 가져오는 것을 variable-lookup이라 합니다. 이것 역시 안쪽 스코프에서 바깥 스코프의 변수를 가져오는 것은 가능하지만 그 반대는 불가능합니다.

*inner block 스코프와 inner function 스코프에 있는 변수들은 상위 스코프의 변수에는 접근 가능하지만 서로의 스코프에는 접근 불가능하다는 것을 볼 수 있습니다.

*스코프 체인 vs 콜 스택: 스코프 체인은 변수의 접근 범위에 대한 개념이고 콜 스택은 함수들의 실행 순서에 대한 개념입니다. 따라서 서로 영향을 미치지 않습니다.

클로저 (Closure)

자바스크립트의 고차 함수에서는 바깥쪽 함수가 리턴된 후에도 내부의 함수에서 바깥쪽 함수의 변수에 접근할 수 있습니다. 아래의 코드에서 외부 함수의 변수 x가 계속 증가하는 것을 볼 수 있습니다 이것을 가능하게 하는 자바스크립트의 기능이 클로저입니다.

function outer(){
    let x = 5;

    function printAndIncrementX (){
        console.log(x);
        x++; // 험수가 호출될 때마다 x의 값이 증가!
    };

    return printAndIncrementX;
};

const myFunc = outer();

myFunc(); // 5
myFunc(); // 6
myFunc(); // 7

클로저로 인해서 외부 함수가 리턴된 이후에도 내부 함수에서 바깥쪽 스코프에 접근 가능하고 변수의 값도 초기화되지 않고 계속 가지고 갑니다.

굳이 클로저가 뭔지 정의하자면 클로저는 실행 문맥이 사라져도 함수가 생성될 때의 변수 환경을 그대로 가지고 있는 폐쇄된(closed) 변수 환경 정도로 정의할 수 있습니다.

사실 클로저의 정의를 알아 둘 필요는 없는 것 같고 클로저를 이용하면 함수가 리턴된 후에도 함수 내부의 변수를 이용 가능하다는 점을 알아두는 것이 중요합니다. 이 점은 React-hooks를 이해하는데 중요합니다.

클로저로 인해서 자바스크립트의 고차 함수는 함수가 리턴된 뒤에도 내부 함수에서 외부 함수의 변수를 그대로 이용 가능하다.

참고자료:
The complete javascript course -Jonas Schmedtmann-
What is Scope and Scope Chain in JavaScript?
Scope and Closure

profile
UX광인이 되고싶어요

0개의 댓글