클로저(Closure)는
1. 내부 함수와
2. 그 함수가 선언될 때의 렉시컬 환경(Lexical Environment)의 조합 이다.
1. 내부 함수: 다른 함수 내부에 정의된 함수
2. 렉시컬 환경: 함수가 선언될 때 생성되는 환경으로, 해당 함수의 스코프에 있는 모든 변수와 함수를 포함.
클로저의 동작: 내부 함수가 외부 함수의 변수에 접근할 수 있고, 외부 함수가 반환된 후에도 이 접근이 유지된다.
어떤 특별한 개념이 아닌 함수의 생성과 함께 자연스럽게 발생하는 게 클로저라는 현상이지만,
우리가 특별히 언급할 때는 주로 상위 스코프에서 선언한 변수를( 렉시컬 환경 ), 내부 함수에서 참조할 경우에
일어나는 특정한 사용 사례나 동작을 가리킨다.
var outer = function () {
var a = 1
var inner = function ( ) {
return ++a
}
return inner
}
var outer2 = outer()
console.log(outer2()) // 출력 : 2
console.log(outer2()) // 출력 : 3
var outer2 = outer() 이 코드로 outer 함수 종료 후,
outer2 변수에 inner 함수는 리턴되게 되는데, 이 inner 함수 내부에는
상위 스코프의 outer 함수의 지역변수 a가 계속 참조 중인 상태이기 때문에
outer 의 실행 컨텍스트는 종료가 됬지만, 내부의 변수는 죽지 않고 살아 있는 상태가 되버렸다.
그리고 console.log(outer2( )) 로 outer2 를 호출하게 되면 inner 실행 컨텍스트가 생성되고,
본인의 내부에는 a 가 없으니 상위 스코프 outer 의 변수를 2로 바꾸게 된다.
그리고 console.log(outer2( )) 가 완전히 종료되면 inner 의 실행 컨텍스트는 사라지지만 a는 계속 참조중이므로
위와 같은 그림이 된다. outer 의 지역변수 a는 계속 살아남아있게 되는데,
전역 컨텍스트가 종료되면(프로그램이 종료되면) 자동으로 a도 사라지게 된다.
강제로 메모리 관리를 위해 현재의 closure( a변수) 를 GC( Garbage Collection ) 대상으로 주려면
outer 2 = null 을 해주어 inner 와의 연결 고리를 끊어주면 된다.
a변수가 사라지지 않으면서 남아 있는 이 현상이 클로저의 특별한 현상이다.
이 말은 함수 종료 후에도 지역변수를 사라지지 않게 컨트롤 할 수 있다는 것이다.
이게 클로저로 얻는 가장 큰 이점이며
1. 데이터 캡슐화
2. 함수 팩토리 생성
3. 콜백 함수에서 외부 변수 접근
등을 할 수 있는 것이다.
1. 데이터 캡슐화의 예시
클로저를 이용해 private 변수를 모방할 수 있다.
function createPerson(name) {
let age = 0;
return {
getName: () => name,
getAge: () => age,
setAge: (newAge) => { age = newAge; }
};
}
const person = createPerson("Alice");
console.log(person.getName()); // "Alice"
person.setAge(30);
console.log(person.getAge()); // 30
2. 함수 팩토리를 만들 때 ( 팩토리 패턴 )
클로저를 이용해 특정 기능을 가진 함수를 생성할 수 있다.
function multiply(x) {
return function(y) {
return x * y;
};
}
const double = multiply(2);
console.log(double(5)); // 10
3. 콜백 함수에서 외부 변수 접근
콜백에서 외부 변수를 올바르게 참조할 수 있게 해준다.
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
// 예상과 달리 5가 5번 출력됨
// 클로저를 이용한 수정
for (var i = 0; i < 5; i++) {
(function(j) {
setTimeout(function() {
console.log(j);
}, 1000);
})(i);
}
// 0, 1, 2, 3, 4가 출력됨
본 내용은 정재남님의 코어 자바스크립트 강의를 바탕으로 만들어졌습니다.
'JavaScript > AboutJS' 카테고리의 다른 글
[Javascript] Iterable, Iterator 프로토콜 (0) | 2024.09.26 |
---|---|
[JavaScript ]CommonJS 모듈 ES 모듈 차이 (0) | 2024.08.26 |
[JavaScript] 이벤트 루프란? (0) | 2024.08.21 |
[JavaScript] This 를 판단하는 기준 (0) | 2024.08.18 |
[JavaScript] 실행 컨텍스트 ( Execution Context ) (0) | 2024.04.24 |