JavaScript

스코프 체인 - 함수에서 어떤 값에 접근이 가능/불가능한가 따져보기

sangchu 2023. 2. 3. 11:47

스코프 (체인)은 함수에서 어떤 값에 접근이 가능/불가능 한가 따져볼 때 사용되는 개념이다.

이때 판별하는 범위는 블록 단위인데, 블록은 중괄호로 감싸여진 범위다.

 

const x = "x";

function c() {
    const y = "y";
    console.log("c"); 
    function b() {
        const z = "z";
        console.log("b"); 
        c(); 
    }
}

function a() { 
    const x = "x";
    console.log("a"); 
    b(); // b를 선언 안했다는 ERROR
}

a(); 
c();

위 코드를 실행하면 함수 a 안에 있는 b를 호출할 때 b를 선언하지 않았다는 에러가 발생한다.

b가 a의 스코프 범위 안에 있지 않기 때문이다.

 

스코프 범위에 있는지 확인하려면 함수 선언을 기준으로 최상위에 있냐/아니냐를 따져보면 알기 쉽다.

c -> anonymous
a -> anonymous
b -> c -> anonymous

앞서 호출 스택 글에서 anonymous는 파일 전체를 뜻하는 함수라고 생각하면 된다고 했다.

위에 작성한 관계를 풀어서 설명해보자면,

c와 a는 anonymous 함수 안에 있고, b는 c 안에 있다.

이러한 관계를 렉시컬 스코프(어휘적 범위)라고 한다.

 

a기준 b는 not defined지만, b기준에서 a에 접근 가능하다.

타고타고 올라가서 anonymous 함수까지 가는데 이 함수 안에는 a가 있어서 가능한 것이다.

 

이를 코드에서 직관적으로 바로 따져보고 싶다면, 들여쓰기를 잘 했다는 가정하에 함수 '선언'을 기준으로 위로 쭉 올라가보면 된다. 만약 다른 선언에서 걸린다면 해당 함수가 부모함수다.

아래 그림에서는 b가 c에서 걸리니 c의 부모함수이고, c와 a는 막힘없이 끝까지 올라가므로 anonymous가 부모 함수임을 알 수 있다.

 

하지만 코드가 길어지면 이렇게 하나하나 올라가 보긴 힘들 것이다. 

이럴때 선언에 대한 지도를 그려보면 직관적으로 알 수 있다. (익숙해지면 머릿속으로도 그려진다고 한다.) 

anonymous -> x, c, a
c -> y, b
b -> z
a -> x

위 관계를 풀어 설명해보자면, anonymous가 선언한건 x, c, a가 있고, c는 y, b를 선언했다는 것이다.

즉 어떤 함수에서 어떤 것이 선언됐는지 그려본 것이다.

 

여기서 x라는 같은 이름의 변수가 2개가 있는데, 같은 이름이어도 위치가 다르면 사용할 수 있다.

a함수에서 x 변수를 사용할때는, a를 먼저 보고 anony를 확인하기 때문이다.

애초에 위 코드에서는 a안에 있는 x변수를 먼저 찾아냈으니 anony까지 찾아보러 갈 일이 없다. 그러므로 문제 없이 쓸 수 있다.

 

 

 

 

 

참고: 제로초 '인간 JS 엔진되기' 강좌를 보고 정리한 글입니다.