본문 바로가기
Script/JavaScript

[JavaScript] Chapter 19. 클로저

by song.ift 2022. 12. 17.

클로저 (Closure)

  • 함수와 함수가 선언된 어휘적 환경(렉시컬 환경)의 조합 => 내부함수가 외부함수 변수에 접근 가능

 

렉시컬 스코프 이해

javascript
닫기
function init() { ​​​​// name은 init에 의해 생성된 지역 변수 ​​​​var name = "Mozilla"; ​​​​ ​​​​// displayName()은 내부 함수이며, 클로저 ​​​​function displayName() { ​​​​​​​​// 부모 함수에서 선언된 변수를 사용 ​​​​​​​​alert(name); ​​​​} ​​​​ ​​​​displayName(); } init();

 

은닉화

  • Information Hiding
  • 외부로부터 데이터를 감추는 것
  • private로 감춤
  • 내부적으로 사용해야하는 경우 감춤
javascript
닫기
// ex) IIFE (즉시 실행 함수) (function() { ​​​​var str = "테스트"; })(); console.log(str); // 외부에서 접근 불가능 = 은닉화 // 은닉화 전 function printFunc(name) { ​​​​this._browser = name; } printFunc.prototype.print = function() { ​​​​console.log(this._browser); } var browser1 = new printFunc("크롬"); browser1.print(); browser1._browser = "모질라"; // 쉽게 접근 가능 browser1.print(); // 은닉화 후 function printFunc(name) { ​​​​var _browser = name; // 외부 접근 불가능한 private 하게 사용 ​​​​ ​​​​function print() { ​​​​​​​​console.log(_browser); ​​​​} ​​​​return print; } var browser1 = new printFunc("크롬"); browser1();

   

클로저의 올바른 정의

함수와 함수가 선언된 어휘적(lexical) 환경의 조합

  • 클로저는 함수를 지칭하고 또 그 함수가 선언된 환경과의 관계라는 개념이 합쳐진것이다.

클로저의 핵심은 스코프를 이용해서, 변수의 접근 범위를 닫는(폐쇄)것에 있다.

  • 외부함수 스코프에서 내부함수 스코프로 접근 불가능하다.
  • 내부함수에서는 외부함수 스코프에서 선언된 변수에 접근 기능하다.
  • 따라서 내부 함수는 외부함수에 선언된 변수에 접근 가능하다.

함수가 호출되는 환경과 별개로, 기존에 선언되어 있던 환경(어휘적 환경)을 기준으로 변수를 조회한다.

  • 외부함수의 실행이 종료된 후에도, 클로저 함수는 외부함수의 스코프, 즉, 함수가 선언된 어휘적 환경에 접근할 수 있습니다.
  • 외부 함수 스코프가 내부함수에 의해 언제든지 참조될 수 있다.
  • 따라서 클로저를 남발할 경우 퍼포먼스 저하가 발생할 수도 있습니다.

상위 스코프의 식별자를 포함하여 쓰여있는 내부 함수 코드 자체를 어휘적 환경(lexical environment)라고 부를 수 있다.

 

 클로저의 혼란스런 정의

클로저는 내부함수가 외부함수의 맥락(context)에 접근할 수 있는 것을 가리킨다?

  • 내부함수(innerFn)가 상위 스코프(예:outerFn)의 식별자를 참조하고 있고, 그 내부함수(innerFn)를 그 상위 스코프(예:outerFn) 바깥에서 사용했을 때, 그 상위 스코프(예:outerFn)의 식별자를 수정할 수 없는 형태이다.
  • 즉, 함수가 정의되었던 위치에서 상위 스코프(예:outerFn)식별자를 기억하고 있는 형태이다.
  • 그래서 중첩함수 뿐만 아니라 내부함수가 외부 스코프에 접근할 수 있는 형태의 클로저도 존재한다.
  • 아래와 같은 클로저의 두가지 예시가 있기 때문이다.
 
// 클로저를 만드는 형태 1. - 중첩함수 function outerFn() { ​​let x = 10; ​​return function innerFn(y) { // innerFn 함수는 클로저다. ​​​​return x = x + y; ​​} } let a = outerFn(); // 외부함수 호출은 한번만. 이제 a 변수는 innerFn 함수를 참조한다. a(5); // 15; a(5); // 20; a(5); // 25;
// 클로저를 만드는 형태 2. - 전역에 선언한 변수를 박스 안에서 함수로 정의하고 전역에서 호출 let globalFunc; { ​​let x = 10; ​​globalFunc = function(y) { // globalFunc 함수는 클로저다. ​​​​return x = x + y; ​​} } globalFunc(5); // 15; globalFunc(5); // 20; globalFunc(5); // 25;

 

클로저는 함수를 리턴하는 함수이다?

  • 함수를 리턴하는 함수가 아니라 내부함수(innerFn)가 상위 스코프(예:outerFn)의 식별자를 참조하고 있고 그 상위 스코프(예:outerFn) 바깥에서 사용했을 때 그 상위 스코프(예:outerFn)의 식별자를 수정할 수 없는 형태이다.

클로저는 외부함수와 내부함수에 의해서 스코프가 분리된다?

  • ‘외부함수와 내부함수에 의해 스코프가 분리된 클로저도 있다’가 맞다.
  • 박스와 내부함수에 의해 스코프가 분리된 클로저도 있다.

댓글