[JavaScript] 변수관리와 스코프 체인

do_large·2020년 11월 26일
0

JavaScript

목록 보기
3/4
post-thumbnail

스코프란?

  • 영역, 범위
  • 변수와 매개변수(parameter)의 접근성과 생존기간
  • 참조 대상 식별자(Identifier, 변수 또는 함수의 이름과 같이 어떤 대상을 다른 대상과 구분하여 식별할수있는 유일한 이름)를 찾아내기 위한 규칙

EC(Excecution Context) 이란?

  • 실행 가능한 코드(전역코드, 함수 내 코드)가 실행되고 있는 구역, 범위에 대한 개념

  • JS엔진은 코드를 실행하기 위해서 실행에 필요한 여러가지 정보를 알고있어야 한다.
    변수(전역변수, 지역변수, 매개변수...), 함수선언, 변수의 유효범위, this...

  • 전역 컨텍스트와 함수 컨텍스트 2가지 종류가 있는데,
    전역 컨텍스트는 함수 내부에서 실행되는 코드를 제외하고 모두 전역 컨텍스트로 볼 수 있다.
    함수 컨텍스트는 함수가 호출이 될 때 생성되고 함수가 동작을 다하게 되면 소멸된다.

JS에서 변수를 관리하는 규칙

1. 함수단위의 변수 관리

  • 자바스크립트에서의 변수는 if, for문 등의 블럭단위로 유효범위(scope)가 설정되는 것이 아니라, 함수단위로 유효범위가 설정되어있다.

    참고
    ECMAScript 6에 도입된 let 키워드를 사용하면 블록레벨 스코프를 사용할수 있다.
    블록레벨 스코프란 코드블록 {} 내에서 유효한 스코프이다.

ex) if문 안에 선언된 c라는 변수를 if문 밖에서 출력할수 있다. 그리고 f함수 내에서 선언된 a 변수를 f함수 외부에서 접근할수 없다.

function f () {
	var a = 3;
    if(true) {
        var c = 2;
    }
  
    console.log(c); //2가 출력
    
    return c;  
}

console.log(a); // a is not defined

2. 실행시의 변수 관리는 렉시컬 영역을 기준으로 한다

lexical scope는 함수를 어디서 호출하는지가 아니라 어디에 선언하였는지에 따라 결정된다. JS에서는 렉시컬스코프를 따르므로 함수를 선언한 시점에 상위스코프가 결정된다.

아래 코드를 보면 foo와 bar 함수를 실행시켰을때 두 함수의 실행결과가 1이 된다는 것을 볼수있다.
foo함수에 x 변수가 선언되어있지만 bar함수가 선언된 위치는 foo의 외부이고 foo의 상위 스코프는 전역이다.
그래서 bar가 선언한 시점에서 x값이 1이므로 foo와 bar함수는 1을 출력하게 된다.

var x = 1;

function foo() {
  var x = 10;
  bar();
}

function bar() {
  console.log(x);
}

foo(); // 1
bar(); // 1

3. 실행시의 변수 검색은 스코프 체인을 이용한다.

스코프체인

  • 하위함수에서 상위함수로의 부모/자식 관계가 정의된 것
function a(){
 var num = 1;
 function b(){
  console.log(num);
 }
 b();
}
a(); // 1

num은 b함수내에 선언되어있지 않지만 b함수를 호출시 num의 값인 1을 출력한다.

a(), b()가 실행되면서 생성된 EC에 의해 b()함수 안에 num이 있는지 탐색하는데, 만약 없다면 함수 b()를 감싸고 있는 외부함수 a()를 탐색하게 된다. 이때 변수 num이 존재하면 그 변수를 참조하게 되고, 없다면 계속적으로 상위함수를 탐색하는 과정을 거친다.

만약 상위함수에서 찾지못해 root인 GLOBAL OBJECT EC까지 갔는데도 변수 a가 없다면 에러가 발생한다.

동작방식


함수 생성시점에 평가된 EC b(), EC a()와 Global 이 생성되면서 outer Lexical Environment에 의해서 연결된다.

함수가 생성되면 Execution Context 가 생성되고, 그리하여 Lexical Environment 상위 Environment Record 와 연결되면서 내부 함수 정보를 탐색할 수 있게 된다.
그리하여 b()함수 에서 함수 a() 에 선언되어 있는 num을 참조하여 에러 없이 결과출력이 가능하게 된다.

https://trustyoo86.github.io/javascript/2017/11/18/javascript-variables-scope-chain.html
https://tyle.io/blog/54
https://poiemaweb.com/js-scope
http://www.nextree.co.kr/p7363/

0개의 댓글