본문 바로가기
javascript

scope

by rami_ 2024. 3. 26.

함수가 선언될 당시의 렉시컬 환경을 기억하는 함수이다.

함수가 선언될 당시의 주변 환경(지역변수, 상위 스코프의 변수, 전역변수)을 기억한다.

 

내부 함수는 자신을 둘러싼 외부 함수의 변수에 접근할 수 있고, 이는 내부 함수가 외부 함수의 스코프에 있는 변수들을 기억하기 때문이다.

 

예제를 통해 좀 더 깊게 알아보자.

 

1. 내부함수 + 외부함수

function outerFunction() {
  var outerVar = 'i am from outerFunction';
  
    function innerFunction1() {
      console.log(outerVar);
    }
    
    function innerFunction2() {
      var outerVar = 'i am from innerFunction2';
      
      innerFunction1();
    }
    
    return { innerFunction1, innterFunction2 };
}

const { innerFunction1, innterFunction2 } = outerFunction();

innerFunction1();
innerFunction2();

 

outerFunction을 실행시켜 구조분해 할당으로 innerFunction1과 innerFunction2를 꺼냈으며 이후 함수들을 차례로 실행시켰다.

outerFunction이 실행될 때 innerFunction1과 innerFunction2는 함수 선언시 렉시컬환경(지역 변수, 전역 변수, 상위 스코프의 변수)을 기억한다.

innerFuction1이 실행될 때 outerVar를 콘솔에 찍으려고 하는데 이때 기억해두었던 렉시컬 환경에서 변수를 찾게 되는데 지역 변수에는 없기 때문에 상위 스코프의 변수 outerVar를 찾을 수 있고 콘솔에 'i am from outerFunction'를 찍힌다. 

innerFunction2가 실행도리 때 innerFunction1이 실행되는데 이때 또 outerVar를 콘솔에 찍으려고 한다. 함수가 선언될 당시의 렉시컬 환경을 기억하기 때문에 이것도 똑같이  'i am from outerFunction'가 콘솔에 찍힌다.

 

 

2. for문 

var funcs = [];

for (var i = 0; i < 3; i++) {
    funcs[i] = (function(x) {
        return function() {
            console.log(x);
        };
    })(i);
}

for (var j = 0; j < funcs.length; j++) {
    funcs[j]();
}

funcs에 빈 배열을 할당한 후 첫번째 for문이 돌아간다. funcs[i]는 i를 인자로 받는 즉시 실행함수이다. 함수 선언당시의 렉시컬 환경을 기억하므로 i를 각 0,1,2로 기억하게 된다. 이후 2번째 for문에서 funcs를 순서대로 실행하는데 이때 콘솔에 순서대로 0,1,2가 찍히게 된다.

 

3. var, let, const 

function scopeTest() {
  console.log(a, b, c);

  var a = 1;
  let b = 2;
  const c = 3;

  function innerTest() {
    console.log(a, b, c);

    var a = 4;
    let b = 5;
    const c = 6;

    if (true) {
      var a = 7;
      let b = 8;
      const c = 9;

      console.log(a, b, c);
    }

    console.log(a, b, c);
  }

  console.log(a, b, c);
  innerTest();
}

scopeTest();

 

scopeTest를 실행하면 함수 실행 전 호이스팅이 일어나 a, b, c가 호이스팅 되는데 이때 a는 var로 선언되어있기 때문에 undefined가 되며 b,c는 let, const로 선언과 초기화가 이루어져야 변수에 접근이 가능하며 현재는 TDZ 상태이다. 첫번째 콘솔로그는 b,c가 선언과 초기화 되기전에 접근했기때문에 선언 전에는 접근할 수 없다는 ReferenceError가 표출되며 더이상 실행되지 않는다(콘솔로그에는 아무것도 찍히지 않는다).

 

 

'javascript' 카테고리의 다른 글

[LEARN-JS] String, Jest  (0) 2024.07.23
closure  (0) 2024.03.27
hoisting  (0) 2024.03.26
자바스크립트의 비동기처리  (0) 2024.03.18
자바스크립트의 은닉화 그리고 모듈  (3) 2024.03.12