스코프, 클로저

Steve·2021년 4월 14일
0

스코프

  • 정의 : 식별자에 대한 유효범위

스코프와 클로저는 굉장히 밀접한 관계가 있다.

스코프체인.

  • 정의 : '식별자의 유효범위'를 안에서부터 바깥쪽으로 차례로 검색해 나가는 것.

아래 코드는 '스코프 체인'이라는 개념을 사용중이다.

var globalColor = 'red';
 
function foo() {
    var fooColor = 'blue';
 
    function bar() {
        var barColor = 'yellow';
 
        console.log(barColor); // yellow
        console.log(fooColor); // blue
        console.log(globalColor); // red
    }
    bar();
}
foo();

렉시컬 환경(Lexical Environment)은 두 부분으로 나뉜다.
1. 환경 레코드(environment Record) - 식별자 저장 하는 곳
2. 외부 렉시컬환경 참조(outer Environment Reference) -

중첩함수에서 안쪽 함수가 자신의 렉시컬 환경을 뒤져도 변수값을 찾을 수 없을 때
-> 바깥 쪽 함수의 렉시컬 환경을 참조한다. 만약 그래도 없다면?
-> 그 바깥의 렉시컬 환경을 참조한다.
이런식으로 렉시컬 환경이 null이 될때까지 쭉 참조를 이어나가는 것이 스코프체인이다.
아래 그림과 같이 체인처럼 엮어서 참조가 이루어진다.

위 2개를 더 자세히 알아보자.

A함수 내부에 B함수를 선언하고 다시 그 안에 C함수를 선언

function A(){
  var a = 1;
  function B() {
    console.log(a);
    function C() {
      console.log(a);
    }
  }
}

(Lexcial Environment)렉시컬환경에는 2가지가 있다.

  • environment Record : 식별자 저장하는 곳
  • outer Environment Reference : 현재 호출된 함수가 선언될 당시의 렉시컬환경.함수 바로 바깥의 환경을 말함

함수 C의 outerEnvironmentReference는 함수 B의 렉시컬 환경을 참조.
함수B의 렉시컬 환경에 있는 outerEnvironmentReference는 다시 함수B가 선언되던 때(A)의 렉시컬 환경을 참조.

  • 선언 시점의 렉시컬환경을 계속 찾아 올라가면 마지막엔 전역 컨텍스트의 렉시컬 환경이 있을것이다.
    각 outerEnvironmentReference는 오직 자신이 선언된 시점의 렉시컬 환경만 참조하고 있으므로 가장 가까운 요소부터 차례대로만 접근할 수 있고 다른 순서로 접근은 불가. 이런 구조적 특성 때문에 여러 스코프에서 동일한 식별자를 선언한 경우에는 무조건 스코프 체인상에서 가장 먼저 발견된 식별자에만 접근 가능.

스코프는 흔히 { }로 기준을 둘 수있다.
const a = 1;
{
const a = 2;
console.log(a); (1)
}
console.log(a); (2)
(1)줄은 스코프 내에 변수 a가 있기 때문에 그대로 2를 출력한다. 하지만
스코프 안에 변수 a가 없는 상황이라면,?
const a = 1;
{
console.log(a); // 스코프 내에 변수 a가 없기 때문에 바깥 중 가장 가까이 있는 변수를 찾을 것이다. 이것이 스코프체인이다.
}
console.log(a);

레벨

  • 함수 스코프
  • 블록 스코프블록 스코프

종류

  • 전역 스코프: 블록 밖에 있는.
  • 지역 스코프: 블록 안에 있는.

클로저

  • 어떤함수가 그 함수를 둘러싼 환경을 기억하는 것
    애매모호한 설명이다. 클로저를 이해하기 위해서는 먼저 스코프 개념에 대해 알아볼 필요가 있다.

특징)

  • 폐쇄 된 곳이지만 연결고리로 인해 메모리에 있는 데이터를 GC가 제거 안함.
  • 사용될 여지가 있으면 제거 안함

아래의 코드를 눈여겨봐라.
본인은 이 코드로 클로저와 스코프체인을 한 번에 잡을 수 있었다.

if(1 < 2) {
  function f = function() {
 	let abc = 123;
    let ddd = function() {
    	return abc; // 스코프체인에 의해 abc가 스코프에 없으니 상위 스코프 뒤짐.
    }
    return ddd;
  }
 }

const ccc = f();
console.log(ccc()); /// 123

첫번째 for문 내에서 arr[i]에 매핑한 값은 특정 값이 아니라 function() {return i};라는 함수입니다. 해당 함수는 지역변수를 가지고 있지 않으니 나중에 실행될때 본인 스코프를 벗어나서 상위 스코프로 올라가면서 i를 참조하려 할텐데 해당 함수가 실제 실행되는 시점인 두번째 for 문에서는 i값이 이미 첫번째 for문이 끝난시점이라 5로 되어있어서 (var로 선언했기 때문에 블록스코프 이후에도 i가 유지됩니다) 모든 결과값이 5로 통일되는겁니다.

profile
Front-Dev

0개의 댓글