렉시컬 스코프, 클로저

렉시컬 스코프란?

렉시컬 스코프는 JS의 특별한 개념이 아니라 스코프를 결정하는 방법론? 중 하나이다.

  1. 식별자를 어디서 호출하였는지에 따라 상위 스코프를 결정하는 방법.
  2. 식별자를 어디서 선언하였는지에 따라 상위 스코프를 결정하는 방법.

첫 번째 방식을 동적 스코프(Dynamic scope)라 하고,
두 번째 방식을 렉시컬 스코프(Lexical scope) 또는 정적 스코프(Static scope)라 한다.

JS를 비롯한 대부분의 프로그래밍 언어는 두 번째 방식을 따른다고 한다.

JS는 렉시컬 스코프를 따르므로 함수를 선언한 시점에 상위 스코프가 결정된다.
함수를 어디에서 호출하였는지는 스코프 결정에 아무런 의미를 주지 않는다.

let name = '이동욱';

function a() {
  let name = '이동훅'
  bar();
}

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

a(); // ?
b(); // ?

위 예제 코드의 실행 결과는 어떻게 될까?

a() // 이동욱
b() // 이동욱

둘 다 같은 이동욱
즉, 전역 스코프의 name 변수를 참조하여 출력한다.

클로저

클로저 역시 JS 고유의 개념이 아니라 함수를 일급 객체로 취급하는 함수형 프로그래밍 언어에서 사용되는 중요한 특성이다.

MDN 은 클로저에대해 아래와 같이 정의한다.

클로저는 함수와 함수가 선언된 어휘적 환경(Lexical environment)의 조합이다. 클로저를 이해하려면 자바스크립트가 어떻게 변수의 유효범위를 지정하는지(Lexical scoping)를 먼저 이해해야 한다.

머선 말인지 모르겠다.. 예제로 한번 살펴보자.

let name= '이동욱'

const outer=()=>{
	let name ='이동훅'
    const inner=()=>{console.log(name)}
    return inner
}

let inner = outer() 
inner()// '이동욱'

위 에제에서 outer는 내부함수 inner를 반환하고 생을 마감했다.
즉, 함수 outer는 실행된 이후 콜스택에서 제거되었으므로 함수 outer의 name 또한 더이상 유효하지 않게 되어 변수 name에 접근할 수 있는 방법은 없을듯하다

하지만 위 코드의 실행 결과는 변수 name값인 '이동욱' 이다.

이처럼 자신을 포함하고 있는 외부함수보다 내부함수가 더 오래 유지되는 경우, 외부 함수 밖에서 내부함수가 호출되더라도 외부함수의 지역변수에 접근할 수 있는 함수를 클로저라고 부른다.

다시 MDN 정의를 살펴보자.

클로저는 함수함수가 선언된 어휘적 환경(Lexical environment)의 조합이다.

위 정의에서 "함수"A 는 반환된 내부함수를 의미하고, "함수가 선언된 어휘적 환경"B는 내부 함수가 선언됐을 때의 스코프를 의미한다.
즉, 클로저는 반환된 내부함수가 자신이 선언됐을 떄의 환경(Lexical environment)인 스코프를 기억하여 자신이 선언됐을 때의 스코프 밖에서 호출되어도 그 스코프에 접근할 수 있는 함수를 말한다.

조금 더 간단히 하면 클로저는 자신이 생성될 때의 스코프를 기억하는 함수 라고 할 수 있다

좋은 웹페이지 즐겨찾기