클로저
- 함수가 자신이 생성될 때의 환경(스코프)을 기억하고 그 환경의 변수 함수 등에 접근할 수 있게 해주는 특성
- 내부 함수에서 외부 함수의 변수에 접근할 수 있다.
- 외부 함수의 실행이 끝난 후에도 내부 함수는 외부 함수의 변수를 기억한다.
function outerFunction() {
let outerVariable = '외부 변수';
function innerFunction() {
console.log(outerVariable); // 외부 함수의 변수에 접근 가능
}
return innerFunction;
}
const closure = outerFunction();
closure(); // '외부 변수' 출력
내부함수를 외부로 전달하는 방법
1. 함수 반환 (return)
function outerFunction() {
let count = 0;
// 내부 함수를 직접 반환
return function() {
return ++count;
};
}
const counter = outerFunction();
console.log(counter()); // 1
console.log(counter()); // 2
2. 콜백 함수로 전달
클로저의 활용
1. 접근 권한 제어(정보 은닉)
- 외부에서 직접 접근할 수 없는 변수를 만들어 정보를 보호할 수 있다.
- 외부에 제공할 정보들을 모아서 return 하고, 내부에서 사용할 정보들은 return 하지 않음으로써 접근 권한을 제어할 수 있다.
function createCounter() {
let count = 0; // 외부에서 직접 접근 불가능한 비공개 변수
return {
increment: function() {
count++;
},
getCount: function() {
return count;
}
};
}
const counter = createCounter();
counter.increment();
counter.increment();
console.log(counter.getCount()); // 2 출력
* count 변수에 직접 접근할 수 없지만, increment 와 getCount 를 통해 안전하게 접근할 수 있음
2. 콜백함수 내부에서 외부 데이터 사용
- 클로저를 사용하여 콜백 함수 내에서 외부 스코프의 변수에 접근할 수 있다.
function fetchData(callback) {
const data = { id: 1, name: "John" };
setTimeout(() => callback(data), 1000);
}
function processUser(userId) {
let user;
fetchData((data) => {
user = data;
console.log(`User ${userId}: ${user.name}`);
});
}
processUser(1); // 1초 후 "User 1: John" 출력
3. 부분 적용 함수
- 기존 함수의 일부 인자를 미리 고정시켜 새로운 함수를 만드는 기법
- 여러 인자를 한 번에 고정할 수 있으며 남은 인자를 모두 한번에 전달한다.
// 기본 함수
function add(a, b, c) {
return a + b + c;
}
// 부분 적용 함수 구현
function partial(fn, ...fixedArgs) {
return function(...remainingArgs) {
return fn(...fixedArgs, ...remainingArgs);
};
}
// 사용 예시
const addFive = partial(add, 5);
console.log(addFive(2, 3)); // 10 (5 + 2 + 3)
console.log(addFive(1, 4)); // 10 (5 + 1 + 4)
4. 커링 함수
- 다중 인자를 받는 함수를 단일 인자를 받는 함수들의 연속으로 변환하는 기법
- 인자를 하나씩 순차적으로 받으며 각 단계에서 하나의 인자만 처리한다.
// 일반 함수 (다중 인자)
function normalAdd(a, b, c) {
return a + b + c;
}
// 커링 함수 (단일 인자 연속)
function curriedAdd(a) {
return function(b) {
return function(c) {
return a + b + c;
};
};
}
// 사용 방법
console.log(normalAdd(1, 2, 3)); // 6
console.log(curriedAdd(1)(2)(3)); // 6
주의할 점
⚠️ 클로저의 변수들은 계속 메모리에 유지되므로 과도한 클로저 생성은 메모리 누수 위험이 발생할 수 있다.
→ 성능에 영향을 줄 수 있으므로 신중하게 사용하고, 더는 사용하지 않게 된 클로저에 대해서는 메모리를 차지하지 않도록 관리해줄 것!
어떻게? - 참조 카운트 제거하기
- 식별자에 참조형이 아닌 기본형 데이터 null 할당
let closureFunction = (function() {
let privateData = 'important data';
function innerFunction() {
return privateData;
}
return innerFunction;
})();
// 더 이상 사용하지 않을 때
closureFunction = null;
- 꼭 필요한 경우에만 클로저 사용하기
'자바스크립트' 카테고리의 다른 글
클래스(class) (0) | 2024.12.19 |
---|---|
프로토타입(prototype) (0) | 2024.12.18 |
콜백함수 (0) | 2024.12.14 |
this (0) | 2024.12.13 |
실행컨텍스트(Execution Context) (0) | 2024.12.03 |