본문 바로가기
프로그래밍/Javascript & React

[Javascript] 렉시컬 스코프(Lexical Scope), 스코프 체인(Scope Chain), 클로저(Closure)

by Dean30 2022. 1. 13.
728x90

[Javascript] 렉시컬 스코프(Lexical Scope), 스코프 체인(Scope Chain), 클로저(Closure)

 

먼저 

자바스크립트의 실행문맥중 렉시컬환경에 대해 알아보자

 

렉시컬 환경(Lexical Environment)

자바스크립트 엔진이 실행을 위해 모아놓은 자원환경이다.

key-value 형식으로 구성되며, 유효범위에 있는 변수와 함수, 객체들을 모아놓은 곳이라 생각하면 된다.

스크립트 전체, 실행중인 함수, 코드블록 등은 자신만의 렉시컬 환경을 갖는다.

 

 

렉시컬 환경 구성

  • 환경레코드 - 렉시컬 환경에서 모든 지역변수를 property로 저장하고 있는 객체이다. (this, 함수일 경우 매개변수 포함)
  • 외부 렉시컬환경 - 현재 렉시컬 환경보다 상위의 렉시컬환경. 스크립트는 최상위 렉시컬환경이다.(글로벌)

자바스크립트의 함수에는(전체에서도) 이 렉시컬환경을 가지고 있다.

 

외부 렉시컬 환경을 참조하는 과정

렉시컬 환경이 만들어질 때, Environment라는 숨김 프로퍼티가 만들어진다. 여기에 외부렉시컬 환경이 저장되어있으며, 지역내에서 참조할 값이 없ㅇ르 경우 프로퍼티에 접근하여 외부 렉시컬 환경을 참조하게 되는데, 값이 없을 경우 최상위 렉시컬 환경까지 검색하게 되는 체이닝 과정이 일어난다. 즉 이 숨김 프로퍼티 때문에 클로져라는 용어가 사용되는 듯 하며, 모든함수는 클로저하고 할 수 있다.

 

 

동적 스코프와 렉시컬(정적) 스코프

 

예제 1)

var x = "global";

function outer() {
  var x = "local";
  inner();
}

function inner() {
  console.log(x);
}

outer();
inner();

 

렉시컬스코프(Lexical scope) = static scope

함수 선언을 기준으로 스코프가 정해진다. (코드가 쓰여진 순간에 이미 스코프 체인이 정해짐, 함수 실행 순서와 상관 없음)

outer() //global
inner() //global

 

동적스코프

함수 호출을 기준(함수 실행 순서)으로 스코프가 정해진다. (상위 스코프가 가장 최근에 실행되었던 함수의 스코프가 된다)

outer() //local
inner() //global

 

예제 2)

var name = "zero";
function log() {
	console.log(name); // zero
}

function wrapper() {
	var name = 'nero'; // 1)
	name = 'nero';     // 2)
        log();
}
wrapper(); // 1) zero 2) nero

스코프 체인에서 log()와 wrapper()의 상위 스코프가 어떤 것인지 생각하면 알 수 있다.

 

 

클로저(Closure)

클로저란 외부 환경(변수)을 기억하고 이 외부 환경(변수)에 접근할 수 있는 함수를 의미한다.

즉, 함수와 렉시컬 환경의 조합이다.

자바 스크립트의 함수는 생성될 당시의 환경을 기억하고 저장하며 이를 통해 외부 렉시컬 환경에 대한 참조가 가능하므로, 모든 함수가 클로저라고 할 수 있다.

개인적 의견으로는 렉시컬환경이 만들어질때 Environment라는 숨김 프로퍼티가 생기고 여기에 외부 렉시컬 환경이 저장되므로 클로져라는 용어가 사용된듯 하다.

 

vad d = "D";

function outer() {
	var a = 1;
    var b = "B";
    
    function inner() {
    	var a = 2;
        console.log(b);
   	}
    return inner
}

var someFun = outer();
someFun(); // "B"

보통 다른 언어같으면 someFun()에서 console.log(b)의 값이 출력되지 않아야한다.

하지만, 자바스크립트는 렉시컬 환경을 가지므로 생성한 시점에 스코프 체인을 들고 있는다.

그래서 "B"가 출력 가능하다.

즉 외부변수 b에 접근이 가능하므로 inner() 함수는 클로저이다.

그리고 outer를 오출하지 않아 원래는 외부변수 b에 접근이 불가능한데, 이것이 가능하다는 점이 자바스크립트 클로저 함수의 매우 특이한 점이다.

 

 

 

 

클로저를 통한 은닉화

TBC

 

 

 

 

참조

- https://www.youtube.com/watch?v=MbYShFxp-j0 

- https://velog.io/@hotdari90/%EC%8A%A4%EC%BD%94%ED%94%84%EC%B2%B4%EC%9D%B8%EA%B3%BC-%ED%81%B4%EB%A1%9C%EC%A0%80

- https://velog.io/@gytlr01/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%A0%89%EC%8B%9C%EC%BB%AC-%ED%99%98%EA%B2%BDLexical-Environment

- https://www.youtube.com/watch?v=fynHf9oGuvw

 

728x90

댓글