일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 챗봇
- 카카오
- closure
- async
- 함수
- callback
- await
- 객체
- 오픈빌더
- 배열
- 변수
- 오픈채팅
- es6
- 자연어처리
- 카카오톡채널
- ReactNative
- es7
- 자바스크립트
- trim
- 순수함수
- 플러스친구
- developers
- JavaScript
- Promise
- 유사배열객체
- 콜백함수
- callbackhell
- expo
- vuejs
- arguments
- Today
- Total
말랑말랑 LAB
[JavaScript] 클로저 본문
자바스크립트 클로저
o 클로저(Closure) 정의
" 자기 자신이 정의된 환경에서 함수 안에 있는 자유 변수의 식별자 결정을 실행한다. " (모던 자바스크립트 입문)
" 클로저는 자신이 생성될 때의 스코프에서 알 수 있었던 변수를 기억하는 함수다 " (함수형 자바스크립트 프로그래밍)
“A closure is the combination of a function and the lexical environment within which that function was declared.” (MDN)
클로저는 함수와 그 함수가 선언됐을 때의 렉시컬 환경(Lexical environment)과의 조합이다.
클로저에 대한 여러 정의가 있는데, 공통적인 부분을 꺼내보면, 클로저는 생성될 때의 환경(스코프)과 관련이 있다는 것이다.
다음과 같은 코드가 있다고 해보자.
함수 outerFunc 내에서 내부함수 innerFunc가 선언되고 호출되었다.
이때 내부함수 innerFunc는 자신을 포함하고 있는 외부함수 outerFunc의 변수 x에 접근할 수 있다.
함수 innerFunc가 함수 outerFunc의 내부에 선언되었기 때문이다.
즉, 함수 innerFunc가 선언(생성)될 때, 상위 스코프(렉시컬 스코프)는 함수 outerFunc가 되는데, 이를 기억하고 있다는 것 !!
내부함수 innerFunc가 outerFunc의 변수 x에 접근하는 과정에서 상위 스코프에 접근할 수 있는 것은
렉시컬 스코프의 레퍼런스를 차례대로 저장하고 있는 실행 컨텍스트의 스코프 체인을 자바스크립트 엔진이 검색하였기에 가능한 것1) innerFunc 함수 스코프(함수 자신의 스코프를 가리키는 활성 객체) 내에서 변수 x를 검색 --> 검색 실패 !
2) innerFunc 함수를 포함하는 외부 함수 outerFunc의 스코프(함수 outerFunc의 스코프를 가리키는 함수 outerFunc의 활성 객체)에서 변수 x를 검색 --> 검색 성공 !
- 내부함수 innerFunc를 함수 outerFunc에서 호출하는 게 아니라 반환한다면?
- 함수 outerFunc는 내부함수 innerFunc를 반환하고 소멸
- 즉, 함수 outerFunc는 실행된 이후 콜스택(실행 컨텍스트 스택)에서 제거되었으므로 함수 outerFunc의 변수 x 또한 더이상 유효하지 않게 되어
변수 x에 접근할 수 없을 것 같은데, 위 코드의 실행 결과는 변수 x의 값인 10이다. - 이미 life-cycle이 종료되어 함수 outerFunc은 실행 컨텍스트 스택에서 제거되었지만, 지역변수 x에 접근하고 있다 !
- 이처럼 자신을 포함하고 있는 외부함수보다 내부함수가 더 오래 유지되는 경우,
외부 함수 밖에서 내부함수가 호출되더라도 외부함수의 지역 변수에 접근할 수 있는데 이러한 함수를 클로저(Closure)라고 부른다.
(클로저를 다시 정의)
클로저는 반환된 내부함수가 자신이 선언됐을 때의 환경(Lexical environment)인 스코프를 기억하여
자신이 선언됐을 때의 환경(스코프) 밖에서 호출되어도 그 환경(스코프)에 접근할 수 있는 함수를 말한다.
## 아래의 코드를 실행시키면 어떤 결과가 나올지 예상을 먼저 해보고, 실행해보자 !
## 위 코드는 다음과 같은 과정으로 실행된다.
o 클로저의 활용
클로저는 자신이 생성될 때의 환경(Lexical environment)을 기억해야 하므로 메모리 차원에서 손해를 볼 수 있다.
그렇다면, 왜 클로저를 사용할까?클로저가 유용하게 사용되는 상황에 대해 살펴보자 !
- 클로저가 가장 유용하게 사용되는 상황은 현재 상태를 기억하고 변경된 최신 상태를 유지하는 것이다. 아래 예제를 살펴보자.
|
① 즉시실행함수는 함수를 반환하고 즉시 소멸
② 클로저를 이벤트 핸들러로서 이벤트 프로퍼티에 할당
③ 버튼을 클릭하면 이벤트 프로퍼티에 할당한 이벤트 핸들러인 클로저가 호출됨
|
- 이처럼 클로저는 현재 상태(위 예제의 경우 .box 요소의 표시 상태를 나타내는 isShow 변수)를 기억하고 이 상태가 변경되어도 최신 상태를 유지해야 하는 상황에 매우 유용하다.
- 만약 자바스크립트에 클로저라는 기능이 없다면 상태를 유지하기 위해 전역 변수를 사용할 수 밖에 없다.
- 전역 변수는 언제든지 누구나 접근할 수 있고 변경할 수 있기 때문에 많은 부작용을 유발해 오류의 원인이 되므로 사용을 억제해야 한다.
- 버튼이 클릭될 때마다 클릭한 횟수가 누적되어 화면에 표시되는 카운터를 만들어보자. 이 예제의 클릭된 횟수가 바로 유지해야할 상태이다.
- 정보의 은닉
이번에는 생성자 함수 Counter를 생성하고 이를 통해 counter 객체를 만들어보자.
|
o 생성자 함수 Counter는 increase, decrease 메소드를 갖는 인스턴스를 생성
o counter는 this에 바인딩된 프로퍼티가 아니라 변수
|
'JavaScript > JavaScript 스터디' 카테고리의 다른 글
[JavaScript] 이터레이터와 제너레이터 (0) | 2019.01.05 |
---|---|
[JavaScript] 고차 함수 (0) | 2019.01.05 |
[JavaScript] 함수의 정의 (0) | 2019.01.05 |
[JavaScript] 제어문 (0) | 2018.12.28 |
[JavaScript] 모던 자바스크립트 입문 - 4장 객체와 배열, 함수의 기초 (0) | 2018.12.14 |