티스토리 뷰

Frontend/Javascript

# Javascript 클로저

zoeful 2020. 8. 30. 17:32

 

이번주는 자바스크립트 클로저(Javascript closure)에 대해서 정리해보려고 한다.

클로저라는 말만 들었을땐 스펠링이 closer일꺼라고 생각했는데,,, closure일 줄이야 

이것도 안찾아봤으면 언젠가 쪽팔림을 감수해야했던 날이 왔을지도 모른다 ㅎㅎㅎ

이번주에도 개발자스러워지기 위해 또 하나 공부해가기><

 

클로저란?

함수 + 함수를 둘러싼 환경 (Lexical environment)

 

함수를 둘러싼 환경이란 렉시컬 스코프를 말하는데 렉시컬 스코프에서는 소스코드가 작성된 그 문맥에서 결정된다.

현대 프로그래밍에서 대부분의 언어들은 렉시컬 스코프 규칙을 따르고 있다.

 

자바스크립트에서 클로저는 함수가 생성되는 시점에 생성된다.

따라서 개념적으로 자바스크립트의 모든 함수는 클로저이지만, 실제로 우리는 자바스크립트의 모든 함수를 전부 클로저라고 부르지는 않는다.

 

클로저는 어떤 데이터(어휘적 환경)와 그 데이터를 조작하는 함수를 연관시켜주기 때문에 유용하다.

이것은 객체가 어떤 데이터와(그 객체의 속성) 하나 혹은 그 이상의 메소드들을 연관시킨다는 점에서 객체지향 프로그래밍과 분명히 같은 맥락에 있다.

 

아래 예시들을 통해 클로저에 대해 정확하게 알아보도록 하자.

 


 

function foo() {
    var color = 'blue';
    function bar() {
        console.log(color); // 'blue'
    }
    bar(); // 'blue'
}
foo(); // 'blue'

 

위 예시를 보면 bar함수가 클로저라고 생각할 수 있다.

bar함수 foo함수 안에 속해있고,  foo함수의 스코프를 외부 스코프 참조로 저장한다.

그리고 bar함수는 렉시컬 스코프 체인을 통해 foo함수 color를 정확히 참조할 것이다.따라서 bar함수를 클로저라고 오해할 수 있을것이다.

 

하지만 여기서의 bar함수는 클로저라고 부르기 어렵다.

bar함수는 foo함수 안에서 정의되고 실행되었을 뿐 foo함수 밖으로 나와서 실행된것이 아니기 때문에 클로저라고 부르지 않는다.

 


 

var color = 'red';
function foo() {
    var color = 'blue';
    function bar() {
        console.log(color); // 'blue'
    }
    return bar; 
}
var baz = foo(); // 'blue'
baz(); // 'blue'

 

bar함수는 color를 찾아 출력한다. 위와 같이 bar함수 foo함수 안에 속해있고, foo함수의 스코프를 외부 스코프 참조로 저장한다. 그리고 bar함수는 렉시컬 스코프 체인을 통해 foo함수 color를 정확히 참조하여 return 할 것이다.

 

bar global baz란 이름으로 데려와 global에서 baz(=bar)를 호출했다. baz에는 bar함수가 담기게 되고, bar는 자신의 스코프에서 color를 찾는다.

 

 

 

하지만 bar에는 선언된 color값이 없기때문에 자신의 외부 환경 참조인 foo의 스코프를 뒤진다.

때문에 당연히 blue가 출력되는 것이다.

 

bar함수는 자신이 생성된 렉시컬 스코프에서 벗어나 global에서 baz라는 이름으로 호출되었다.

스코프 탐색을 현재 실행 스택과는 관계없는 foo함수를 거쳐갔다.

baz를 bar함수로 선언할때는 이미 bar함수의 외부 환경을 foo로 결정한 이후이다.

따라서 bar함수의 생성과 직접적인 관련이 없는 global에서 아무리 호출하더라도 여전히 foo함수에서 color를 찾게 되는 것이다. 이러한 bar함수를 클로저라고 부른다.

 

추가적으로 foo함수의 렉시컬환경 인스턴스는 foo(); 수행이 끝난 이후 GC(garbage collector)가 회수해야 하는데

앞에 설명했듯 bar함수는 여전히 바깥 렉시컬 환경인 foo함수의 렉시컬 환경을 계속 참조하고 있고,

 bar함수 baz가 여전히 참조하고 있기 때문에 회수되지 않는것을 알 수 있다.

 

Reference : https://meetup.toast.com/posts/86

'Frontend > Javascript' 카테고리의 다른 글

# 데이터 타입  (0) 2020.10.21
# TypeScript를 시작하며  (0) 2020.09.29
# export / import  (0) 2019.10.31
# express 라우트 메소드 .get()과 .post()  (0) 2019.09.16
# Excel export network error  (1) 2019.08.22
댓글
공지사항