클로저 (Closure)
- 함수와 함수가 선언된 어휘적 환경(렉시컬 환경)의 조합 => 내부함수가 외부함수 변수에 접근 가능
렉시컬 스코프 이해
function init() {
// name은 init에 의해 생성된 지역 변수
var name = "Mozilla";
// displayName()은 내부 함수이며, 클로저
function displayName() {
// 부모 함수에서 선언된 변수를 사용
alert(name);
}
displayName();
}
init();
은닉화
- Information Hiding
- 외부로부터 데이터를 감추는 것
- private로 감춤
- 내부적으로 사용해야하는 경우 감춤
// 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)의 식별자를 수정할 수 없는 형태이다.
클로저는 외부함수와 내부함수에 의해서 스코프가 분리된다?
- ‘외부함수와 내부함수에 의해 스코프가 분리된 클로저도 있다’가 맞다.
- 박스와 내부함수에 의해 스코프가 분리된 클로저도 있다.
'Script > JavaScript' 카테고리의 다른 글
[JavaScript] Chapter 21. 이벤트 다루기 (0) | 2022.12.19 |
---|---|
[JavaScript] Chapter 20. 이벤트 (0) | 2022.12.17 |
[JavaScript] Chapter 18. 비동기 (0) | 2022.12.17 |
[JavaScript] Chapter 17. 클래스 (0) | 2022.12.16 |
[JavaScript] Chapter 16. Prototype(프로토타입) (0) | 2022.12.16 |
댓글