본문 바로가기

자바스크립트

[javascript] (함수)스코프와 스코프 체인?

반응형

스코프(scope)가 뭐시여??

자바스크립트는 기본적으로 변수를 어느 부분에 정의 하느냐에 따라서 변수가 접근이 가능한 지점을 결정한다.  전역에 변수를 선언하면, 그 변수는 어느 곳에서든 참조할 수 있지만, 만일 함수 내부나 for문과 같은 반복문, if문과 같은 조건문의 { } 내부에 변수를 선언하게 되면, 그 이외의 지역에서는 해당 변수를 참조하거나 접근할 수 없게 된다.

 

이렇듯, 자바스크립트에는 변수가 접근하거나 혹은 변수 자체에 접근할 수 있는 유효한 범위가 존재하며, 이를 유효 범위 혹은 스코프라고 한다. 이를 더 쉽게 말하면, '한계(리미트)' 라고 보면 될 것 같다.

 

전역 스코프와 지역 스코프 

다음과 같이 접근하면 과연  i 는 출력이 될까? (참고로  함수를 둘러싼  {  } 까지를 함수 스코프라고 한다.)

let i = 1;

function meFun(){  // {    } -> 요걸로 둘러쌓인 것까지 위치를 함수 스코프라 한다.
                     //{   } 내부를 지역 스코프라 한다.       
    console.log(i)
}
meFun();

// 함수 스코프는 함수가 미칠 수 있는 영향 범위를 의미한다.
// 지역 스코프는 함수, if, for 등에서 {       } -> 요것의 내부 범위를 아우르는 말이다.
// ㄴ 따라서 함수 스코프 <= 지역 스코프 이렇게 이해해도 무방하다

정답은 '1' 이 정상적으로 출력이 된다. 그 이유는 렉시컬 스코프로 인한 것이다.  괜히 이것을 언급한 이유는 다음 예시에서 찾아볼 수 있다. 

 

자, 이 경우에는 과연 ' i ' 는 무사히 탈출할 수 있을까? 

function meFun(){
    let i = 1;
   
}
meFun();
 console.log(i);

 

결과는 탈출이 불가능하다. 즉, 출력이 되지 않는다. 다음의 문구와 함께 말이다. 

 i is not defined

 

이러한 차이가 생기는 이유는 서두에 언급했듯이 변수가 선언된 위치에 따라서 변수가 접근할 수 있는 범위가 달라지기 때문이다.

 

즉, 변수가 전역에서 선언된다면 그 변수는 어디서든 접근이 가능한 변수가 되지만, 함수, if, for문 등의 블록 범위에 선언된 변수는 딱 그 범위 내에서만 접근이 가능한 변수가 된다. 

 

아니, 그래서 왜 이런 차이가 생기는거야?   자바스크립트의 스코프 체인 때문에

자바스크립트 엔진에는 스코프 체인이라는 자료구조를 함수를 선언할 때 생성한다. 생성된 스코프 체인은 단방향으로 이어지는데, 이것이 이어지는 방향이 함수 스코프 내부(지역 스코프) 에서 외부(전역 스코프) 방향이다. 

 

이에 대해 그림으로 그려보고 싶었는데, 똥손이라 그냥 예시 코드로 대체해 본다. 

 

아래 예시를 보면 전역 변수에 있는  global 변수는 함수 스코프의 어느 하위 지역 스코프 내에서도 접근이 가능했지만,

상위 스코프에서 하위 스코프의 변수에 접근하려고 하면 정의되지 않았다고 하며 에러가 뜬다. 

 

마치 내리갈굼을 보는 듯 하다.

let global = '나 전역변수임 불만있으면 부르삼';

function a(){
    let A ="나 a 지역"
    console.log("a:",global); // 호출 가능
      
    function b(){
        let  B="나 b 지역"
        console.log("b:",global); // 호출 가능

        function c(){
            let  C="나 c 지역"
            console.log("c:",global); // 호출 가능
            console.log("c:",D); // 호출 불가능 -> ReferenceError: D is not defined
           
            function d(){
                let  D="나 d 지역"
                console.log("d:",global); // 호출 가능
                console.log("d:",A); // 호출 가능
            }
            d();
        }
        c();
    }
    b();
}
a();

 

 

 

반응형