[Javascript] 콜 스택, 스코프 체인, 변수 은닉화

YES31·2022년 11월 18일
0

javascript

목록 보기
4/4
post-thumbnail

let, const, var, function 의 실행원리

let 변수와 const는 ES6 이후 스펙에서 새롭게 등장한 변수이다. 그래서 브라우저 배포용 코드같은 경우는 아직도 var변수만 사용되는 경우도 있다고 한다.

var,let,const 를 구분하는 가장 중요한 점을 요약하면
1.값 변경 가능 유무
2.스코프 범위
3.호이스팅 가능 유무

우선 순위는 const -> let -> var 이라고 하니 최대한 우선순위에 맞춰서 써야합니다.


1.값 변경 가능 유무

var와 let을 값이 선언된 이후에도 값을 변경할 수 있지만, const는 생성할 때 선언된 초기값을 변경할 수 없습니다.

2.함수스코프 vs 블록스코프

var은 함수스코프를 가지지만,
let과 const 변수는 블록 스코프를 가지게 됩니다.

3.호이스팅 가능 유무

var는 호이스팅이 가능하지만,
let과 const는 호이스팅이 불가능합니다.

2.번의 부가설명을 드리자면 블록스코프란 변수가 선언된 {블록}이 해당 변수를 사용할 수 있는 영역(스코프)이라는 뜻입니다.

이렇게 if문을 감싸고 있는 {블락} 이 변수를 사용할 수 있는 영역이 되어 변수가 구분되어 진다.

위와 같이 let을 쓰면 if안과 밖으로 스코프가 달라지지만 (블록 안과 밖의 스코프가 달라져서 변수 이름이 같아도 값이 대체되지 않아 같은 스코프에는 같은 이름 사용 불가하다), name을 var변수로 선언 했을 경우에는 if 안과 밖이 같은 스코프가 되어서 "Uncaught SyntaxError: Identifier 'name' has already been declared"오류가 뜨게됨

function()의 원리

엔진이 함수를 실행하는 방법

함수를 실행하기 위해서는 이름(식별자)이 필요합니다. 이름이 있어야 스코프에서 값을 참조할 수 있기 때문입니다.

예를 들어 function foo() {} 를 정의하면 foo() 구문을 이용해 함수를 실행할 수 있습니다.

엔진이 함수 선언문을 만나면 식별자를 관리하는 특별한 집합(EnviromentRecord)에 함수의 이름을 식별자로 넣고 함수 객체를 생성하여 참조합니다. 그리고 함수 실행 구문 중 foo를 만나면 값을 스코프를 통해 가져옵니다. 그 다음 구문이 () 이므로 실행 가능하다면 실행합니다.

만약 스코프에서 식별자를 찾지 못했다면 참조 에러(ReferenceError)를 출력하고, 식별자는 찾았지만 실행할 수 없는 타입이라면 타입 에러(TypeError)를 출력합니다.

not(); // ReferenceError: not is not defined

var foo = 'some';
foo(); // TypeError: foo is not a function

.
.
.

실행 컨텍스트와 콜 스택

먼저 실행 컨텍스트는 자바스크립트 코드가 실행되는 환경을 의미한다.
자바스크립트에서 대표적으로 두 가지 타입의 Execution context가 있다.

실행할 코드에 제공할 환경 정보들을 모아놓은 객체들로
자바스크립트의 동적 언어로서의 성격을 가장 잘 파악할 수 있는 개념이다.

  1. Global Execution context
    자바스크립트 엔진이 처음 코드를 실행할 때 Global Execution Context가 생성된다. 생성 과정에서 전역 객체인 Window Object (Node는 Global) 를 생성하고 this가 Window 객체를 가리키도록 한다.

  2. Function Execution context
    자바스크립트 엔진은 함수가 호출 될 때마다 호출 된 함수를 위한 Execution Context를 생성한다.
    모든 함수는 호출되는 시점에 자신만의 Execution Context를 가진다.

자바스크립트는 실행 컨텍스트가 활성화되는 시점에 다음과 같은 현상이 발생한다.

  • 호이스팅이 발생한다(선언된 변수를 위로 끌어올린다)
  • 외부 환경 정보를 구성한다
  • this 값을 설정한다.

call stack

코드가 실행되면서 생성되는 Execution Context를 저장하는 자료구조로 프로그램이 함수 호출을 추적할때 사용한다.

엔진이 처음 script를 실행할 때, Global Execution Context를 생성하고 이를 Call Stack에 push한다.

그 후 엔진이 함수를 호출할 때 마다 함수를 위한 Execution Context를 생성하고 이를 Call Stack에 push 한다.

자바스크립트 엔진은 Call Stack의 Top에 위치한 함수를 실행하며 함수가 종료되면 stack에서 제거(pop)하고 제어를 다음 Top에 위치한 함수로 이동한다.

.
.
.

스코프 체인, 변수 은닉화

스코프는 함수의 중첩에 의해 계층적 구조를 가진다.

변수를 참조할 때, 자바스크립트 엔진은 스코프 체인을 통해 변수를 참조하는 코드의 스코프에서 시작하여 상위 스코프로 이동하면서 선언된 변수를 검색한다.

스코프 체인은 outerEnvironmentReference와 밀접한 관계를 가진다.

💡 스코프 체인은 실행 컨텍스트의 렉시컬 환경을 '단방향'으로 연결한 링크드 리스트

변수 은닉화(variable shadowing)

여러 스코프에서 동일한 식별자를 선언한 경우, 무조건 스코프 체인 상에서 가장 먼저 검색된 식별자에만 접근이 가능하다.

(function s(){
let a = 'hi'
})() //a is not defined

즉, 직접적으로 변경되면 안되는 변수에 대한 접근을 막는것이다.

function hello(name) {
  let _name = name;
  return function () {
    console.log('Hello, ' + _name);
  };
}

let a = new hello('영서');
let b = new hello('아름');

a() //Hello, 영서
b() //Hello, 아름

이렇게 a와 b라는 클로저를 생성하면 함수 내부적으로 접근이 가능하다.

profile
🏀 주니어 개발자

0개의 댓글