코딩기록

JS)모던 자바스크립트 Deep Dive 13장 스코프 본문

프론트/모던 자바스크립트 Deep Dive 책 스터디

JS)모던 자바스크립트 Deep Dive 13장 스코프

뽀짝코딩 2024. 7. 18. 16:40
728x90

13장 스코프

 

13-1. 스코프란?

  • 스코프는 변수 그리고 함수와 깊은 관련이 있음.
  • 변수나 모든 식별자는 자신이 선언된 위치에 의해 다른 코드가 식별자(변수 이름, 함수 이름, 클래스 이름 등)자신을 참조할 수 있는 유효한 범위가 결정되는데 이를 스코프라 함. 즉, 스코프는 식별자가 유효한 범위. 
    • ①은 'local'이라는 값이 나오는데  foo 함수 내에서 선언한 변수 x를 참조하기 때문.
    • ②는 'global'이 나옴. foo함수 내부에 선언된 x를 밖에서 참조 할수 없기 때문에 참조 할 수 있는 맨 위 전역 변수 x를 참조하기 때문.
    • 두개의 x 변수 식별자 이름은 동일하지만 자신이 유효한 범위, 즉 스코프가 다른 별개의 변수.
      • 식별자는 유일해야 하지만 스코프가 달라서 같은 이름의 식별자를 사용할 수 있음.
        • 하지만 ❗❗var 키워드로 선언한 변수는 중복이 가능.
        • 이는 의도치 않게 변수값이 재할당되어 변경되는 부작용이 발생하게 됨.(var 키워드가 없는 것처럼 동작)
          • let이나 const 키워드로 선언된 변수는 같은 스코프 내에서 중복 선언을 허용하지 않음. 

 

 

13-2. 스코프의 종류

1). 전역과 전역 스코프

코드의 가장 바깥 영역(전역)에서 선언된 변수, 어디서든지 참조할 수 있음(함수 내부⭕).

 

 

2). 지역과 지역 스코프

  • 지역은 함수 몸체 내부를 말하고 지역에 변수를 선언하면 지역 스코프를 갖는 지역 변수가 됨. (함수에 의해서만 지역 스코프가 생성)
  • 지역 변수는 자신의 지역 스코프와 하위 지역(중첩 함수) 스코프에서 유효.
  • 그림 13-2에서 inner 함수 내부에서 선언된 x 변수 외에 이름이 같은 전역 변수 x가 존재함. 이때 inner 함수 내부에서 x 변수를 참조하면 전역 변수 x를 참조하는 것이 아니라 inner 참수 내부에서 선언된 x 변수를 참조.
    • 이는 자바스크립트 엔진이 스코프 체인을 통해 참조할 변수를 검색 했기 때문.

 


13-2. 스코프 체인

(덧, 사슬은 고리를 차례로 이어놓은 것.)

스코프가 계층적으로 연결된 것.

  • 모든 스코프는 하나의 계층적 구조로 연결됨.
  • 모든 지역 스코프의 최상위 스코프는 전역 스코프.
  • 변수를 참조할 때 자바스크립트 엔진은 스코프 체인을 통해 변수를 참조하는 코드의 스코프에서 시작하여 상위 스코프 방향으로 이동하며 선언된 변수를 검색.
    • 이를 통해 상위 스코프에서 선언한 변수를 하위 스코프에서도 참조할 수 있음.
  • 자바스크립트 엔진은 코드(전역 코드와 함수 코드)를 실행하기 전 위 그림과 유사한 자료구조인
    1. 렉시컬 환경을 생성.
    2. 변수 선언이 실행되면 번수 식별자가 이 자료구조(렉시컬 환경)에 키로 등록 됨.
    3. 변수 할당이 일어나면 이 자료구조 (렉시컬 환경) 의 변수 식별자에 해당하는 값을 변경.
      • 변수의 검색도 이 자료구조 상에서 이뤄짐.
        • 스코프 체인은 실행 컨텍스트의 렉시컬 환경을 단방향으로 연결한 것. 전역 렉시컬 환경은 코드가 로드되면 곧바로 생성되고 함수의 렉시컬 환경은 함수가 호출되면 곧바로 생성.
        • 23장 실행 컨텍스트에서 자세히...

 

1). 스코프 체인에 의한 변수 검색

  • 자바스크립트 엔진은 스코프 체인을 따라 변수를 참조하는 코드의 스코프에서 시작해서 상위 스코프 방향으로 이동하며 선언된 변수를 검색.
    • 절대 하위 스코프로 내려가면서 식별자를 검색하지 않음.
  • 상위 스코프에서 유효한 변수는 하위 스코프에서 자유롭게 참조할수있지만 하위 스코프에서 유효한 변수를 상위 스코프에서 참조할 수 없다.
    • (위에 코드를 아래 애들이 갖다 쓸수 있지만 아래 코드는 위에서 못 갖다 쓴다. 애들꺼 쓰지마세요~)
    • 스코프 체인으로 연결된 스코프의 계층적 구조는 부자 관계로 이뤄진 상속과 유사.
    • 자식만 부모의 자산을 자유롭게 사용. 부모는 자식의 자산 사용 불가. 스코프 체인도 마찬가지 개념.

 

2). 스코프 체인에 의한 함수 검색

  •    [예제 13-06]
       // 전역 함수
       function foo() {
         console.log('global function foo');
       }
       function bar() {
         // 중첩 함수
         function foo() {
           console.log('local function foo');
         }
         foo();  //①
       }
       
       bar();
    •  
    • [예제 13-06] 호출 순서
    •     [예제 13-06]
          // 전역 함수
          console.log(1);
          function foo() {
           console.log('global function foo', 2);
          }
          console.log(3);
          function bar() {
           // 중첩 함수
           
           console.log(4);
           function foo() {
             console.log('local function foo', 5);
           }
           
           console.log(6);
           foo();  //①
           }
         
            console.log(7);
            bar();
         ==================
         1
         3
         7
         4
         6
         local function foo 5
  • 함수 선언문으로 함수를 정의하면 런타임 이전에 함수 객체가 먼저 생성됨.
  • 자바스크립트 엔진은 함수 이름과 동일한 이름의 식별자를 암묵적으로 선언하고 생성된 함수 객체를 할당.
    • 스코프는 식별자를 검색하는 규칙이라고 표현 할 수도 있음.

 

13-3. 함수 레벨 스코프 

  • 함수 레벨 스코프
    • var 키워드로 선언된 변수는 오로지 함수의 코드 블록(함수 몸체)만을 지역 스코프로 인정.
      •    var x = 1;
           console.log(x);  // 1
           if (true) {
             // var 키워드로 선언된 변수는 함수의 코드 블록(함수 몸체)만을 지역 스코프로 인정.
             // 함수 밖에서 var 키워드로 선언된 변수는 코드 블록 내에서 선언되었다 할지라도 모두 전역 변수.
             // 따라서 x 는 전역 변수. 이미 선언된 전역 변수 x가 있으므로 x 변수는 중복 선언됨. 
             // 이는 의도치 않게 변수 값이 변경(재할당)되는 부작용을 발생시킴.
             var x = 10;
           }
           
           console.log(x);  //  10
    • var 키워드로 선언된 변수는 오로지 함수의 코드 블록만을 지역 스코프로 인정하지만 ES6에서 도입된 let, const 키워드는 블록 레벨 스코프를 지원.
      • 15장 let,const 키워드와 블록 레벨 스코프에서 자세히...
  • 블록 레벨 스코프(block level scope)
    • 코드 블록 ( if, for, while, try/catch 등)

 

 

13-4. 렉시컬 스코프 (Lexical Scope) 

(덧, Lexical Scope:어휘 범위  즉, 변수를 검색할때 함수를 정의한 코드의 문맥을 근거로 판단. 함수 실행 환경x )

  • 함수를 어디서 호출했는지에 다라 함수의 상위 스코프를 결정. (동적 스코프)
  • 함수를 어디서 정의했는지에 따라 함수의 상위 스코프를 결정(정적 스코프)
    • 자바스크립트를 비롯한 대부분의 프로그래밍 언어가 따르는 방법.
  • 함수의 상위 스코프는 언제나 자신이 정의된 스코프.
  • 함수 상위 스코프는 함수 정의가 실행될 때 정적으로 결정 됨.
  • 함수 정의(함수 선언문 또는 함수 표현식)가 실행되어 생성된 함수 객체는 이렇게 결정된 상위 스코프를 기억함.
    • 함수가 호출될 때마다 함수의 상위 스코프를 참조할 필요가 있기 때문.
   [ 예제 13-09 ]
   var x = 1;
   
   function foo() {
     var x = 10;
     bar();
   }
   
   function bar() {
     console.log(x);
   }
   
   foo();
   bar();
  • [ 예제 13-9 ]에서 bar 함수는 전역에서 정의된 함수.
  • 함수 선언문으로 정의된 bar 함수는 전역 코드가 실행되기 전에 먼저 평가되어 함수 객체를 생성.
  • 이때 생성된 bar 함수 객체는 자신이 정의된 스코프, 즉 전역 스코프를 기억함.
  • 그리고 bar 함수가 호출되면 호출된 곳이 어디인지 관계없이 언제나 자신이 기억하고 있는 전역 스코프를 상위 스코프로 사용. 
    • 따라서 위 예제를 실행하면 전역 변수 x의 값 1을 두 번 출력.
    •    [ 예제 13-09 ]
         // 코드 흐름
         var x = 'x';

         console.log(1);
         function foo() {
           console.log(2);
           var x = 10;
           
           console.log(3);
           bar();
         
           console.log(4);
         }
         
         console.log(5);
         function bar() {
           console.log(x);
         }
         
         console.log(6);
         foo();
         console.log(7);
         bar();

         ==================
         1
         5
         6
         2
         3
         x
         4
         7
         x
       
      • 렉시컬 스코프는 클로저와 깊은 관계가 있는데 24장 클로저에서 자세히...
덧),

렉시컬스코프, 즉시 실행 함수, 실행 컨텍스트 를 이해해야 클로저를 이해할수 있음.
렉시컬 스코프는 함수의 상위스코프는 어떻게 결정하냐면 어느 위치에서 함수 정의가 되었는지에따라 결정됨.
정적. 절대 바뀌지 않음.

 

 

 

 

 


참고

도서 - 모던 자바스크립트 Deep Dive -이웅모

이웅모 강사님 홈피  -  https://poiemaweb.com/js-prototype

이웅모 강사님 유튜브  -  https://www.youtube.com/watch?v=0AjTZG6bGq8


✅ 덧, 부분은 스터디 내용을 기억에 의존해서 쓴 글이라 틀린 부분이 있다면 댓글 부탁드립니다.- 뽀짝코딩 주인장-

 

 

반응형
Comments