[JS]스코프와 클로저

goum·2021년 8월 19일
0

Scope

  • 사전적 의미는 범위이다. 그래서 유효범위라고도 부른다.
  • 변수 이름, 함수 이름, 클래스 이름 같은 식별자가 본인이 선언된 위치에 따라 다른 코드에서 자신이 참조될수 있을지 없을지 결정 되는 유효 범위

선언위치에 따른 Scope

  • global scope
    • 함수나 블록에 포함되지 않은 곳에서 정의하는 것으로 어디에서든지 참조할 수 있다.
    • global scope 변수의 선언은 피하는게 좋다. 변수 이름이 중복될 수 있고, 의도치 않은 재할당에 의한 상태 변화로 코드를 예측하기 어렵게 만드므로 사용을 자제하여야 한다.
  • local scope
    • 함수나 블록내에 정의 된 것으로 정의된 블록 또는 함수 내에서만 참조할 수 있다.

레벨에 따른 Scope

  • function-level scope
    • var를 이용한 기존의 변수 선언 스코프
    • 정의된 함수 내에서 참조할 수 있다.
  • block-level scope
    • ES6부터 const와 let을 이용해 지원하기 시작했다.
    • 정의된 코드 블록({…})내에서 참조할 수 있다.

Lexical Scope(정적 범위)

  • 어떤 변수가 함수 스코프 안에 있는지 함수를 정의할 때 알 수 있다는 뜻
  • 함수를 어디서 호출하는지가 아니라 어떤 스코프에 선언하였는지에 따라 결정된다.
let text = 'global';

function foo() {
  console.log(text);
}

function bar() {
  let text = 'bar';
  foo();
}

bar(); //global

Scope Chain

  • 중첩된 함수의 스코프의 계층 구조를 스코프 체인 이라고 한다.
  • 스코프체인은 단방향으로 식별자 참조를 위해 탐색할때 스코프 체인을 안에서 바깥으로 거슬러 올라가면서 찾아서 참조 한다.
  • 서로 다른 local scope내 변수들은 서로 참조할 수 없지만 함수를 중첩하면 외부에서는 안에있는 함수의 변수를 참조할 수 없지만, 안에서는 외부의 변수를 사용할 수 있다.
const a =1;

function outer() {
  const b = 2;
  console.log(a); // 1
  
  function inner() {
    const c = 3;
    console.log(b); // 2
    console.log(a); // 1
  }
  
  inner();
}
outer();

console.log(c) // c is not defined
  • inner 함수에서 a를 참조할 때 먼저 자기 자신의 스코프에서 a를 찾고, 없으면 상위 스코프인 outer 함수 거기도 없다면 또다시 상위 스코프인 전역으로 올라가 a를 찾고, 최종적으로 없다면 not defined를 출력한다. 이렇게 계속해서 체인처럼 꼬리에 꼬리를 물고 상위 스코프를 참조하기 때문에 스코프 체인이라고 한다.

Closure

  • 외부 함수의 실행이 끝나고 외부 함수가 소멸된 이후에도 내부함수가 외부함수의 변수에 접근할 수 있는 구조
  • 자바스크립트는 함수가 호출되면 메모리에 할당하고 종료되면 메모리에서 해제되기 때문에 지역 변수들은 함수를 호출할때마다 값은 값으로 초기화 된다. 하지만 이전에 값을 유지해서 이어 받고 싶다면 클로저를 이용하면 된다.
let num = 1;

function foo() {
  let num = 2;
  
  function bar() {
    console.log(num); // 2
  }
  return bar;
}

const baz = foo();
baz();

위코드에서 보면 2가 출력되는걸 볼수있다. 근데 앞서 말한것처럼 자바스크립트에서 함수가 종료되면 메모리에서 해제되는데 어떻게 num 값에 접근할 수 있는 걸까?
이는 자바스크립트에서 함수가 정의될때 내부슬롯에 상위스코프의 참조를 저장하기 때문이다.
변수를 선언하면 식별자를 관리하기 위한 자료구조가 만들어지고 스코프 체인 또한 물리적으로 그렇게 저장된다.

  • 클로저를 사용하면 외부에 해당 변수를 노출시키지 않고 클로저를 통해서만 참조할 수 있기때문에 외부 사용자가 값을 변경할 수 없다.(캡슐화, 은닉화)

마치며

호이스팅에 이어 스코프와 클로저에 대해 알아보았다. 여전히 렉시컬 환경 실행콘텍스트 같은 개념이 부족해 깊지는 않지만 이해한 부분을 정리해 두었다. 그리고 더 깊은 부분을 다루는 내용의 포스트 들을 참고로 붙여두고 계속 공부해나가면서 해당글은 후에 업데이트 해봐야 겠다.

참고

자바스크립트의 스코프와 클로저 - NHN Cloud
클로저, 그리고 캡슐화와 은닉화 - NHN Cloud
한눈에끝내는 Node.js - goorm

0개의 댓글