6.1 클로저 개념
클로저는 JavaScript에서 가장 강력하고 중요한 개념 중 하나야. 클로저를 통해 함수는 실행 후에도 자신의 렉시컬 환경을 기억할 수 있게 해줘. 이번 강의에서는 클로저의 개념, 특징 및 다양한 사용 예제를 살펴볼 거야.
JavaScript에서 클로저(closure)는 함수와 그 함수가 선언된 렉시컬 환경의 조합이야. 클로저는 함수가 외부 함수가 실행된 후에도 외부 스코프의 변수와 다른 함수에 접근할 수 있게 해줘.
클로저의 주요 속성:
- 렉시컬 환경: 함수가 선언된 컨텍스트로, 선언 시점에 접근 가능한 모든 변수를 포함해.
- 컨텍스트 유지: 클로저를 가진 함수는 외부 함수가 실행 완료된 후에도 외부 스코프의 변수에 접근할 수 있어.
6.2 클로저 사용 예제
예제 1: 간단한 클로저
이 예제에서 innerFunction()은 outerVariable에 접근할 수 있으며 outerFunction()이 실행 완료된 후에도 계속 접근 가능해.
function outerFunction() {
let outerVariable = 'I am from the outer function';
function innerFunction() {
console.log(outerVariable);
}
return innerFunction;
}
const closure = outerFunction();
closure(); // 출력: I am from the outer function
예제 2: 클로저를 사용한 카운터
이 예제에서는 카운터 함수가 count 변수의 값을 저장하고, 호출될 때마다 1씩 증가시켜.
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 출력: 1
console.log(counter()); // 출력: 2
console.log(counter()); // 출력: 3
예제 3: 루프에서 클로저
클로저는 루프에서 변수 값을 저장하는 데 자주 사용돼.
이 예제에서는 배열 arr 내부의 각 함수가 i 변수를 생성 시점의 값으로 "기억"해, let의 블록 스코프 덕분에:
function createArrayWithClosures() {
let arr = [];
for (let i = 0; i < 3; i++) {
arr[i] = function() {
console.log(i);
};
}
return arr;
}
const closures = createArrayWithClosures();
closures[0](); // 출력: 0
closures[1](); // 출력: 1
closures[2](); // 출력: 2
6.3 클로저의 복잡한 사용 시나리오
예제 1: 함수의 부분적 적용 (partial application)
클로저는 일부 인자를 고정된 상태로 유지하여 부분적으로 적용된 함수를 생성할 수 있게 해줘.
이 예제에서는 multiply() 함수가 고정된 인자 a에 b를 곱하는 함수를 반환해.
function multiply(a) {
return function(b) {
return a * b;
};
}
const double = multiply(2);
console.log(double(5)); // 출력: 10
console.log(double(10)); // 출력: 20
예제 2: 데이터 숨기기 (data hiding)
클로저는 비공개 변수와 메서드를 생성하는 데 사용될 수 있어.
이 예제에서는 변수 _name과 _age가 비공개이며 객체의 메서드를 통해서만 접근 가능해:
function createPerson(name, age) {
let _name = name;
let _age = age;
return {
getName: function() {
return _name;
},
getAge: function() {
return _age;
},
setName: function(newName) {
_name = newName;
},
setAge: function(newAge) {
_age = newAge;
}
};
}
const person = createPerson('John', 30);
console.log(person.getName()); // 출력: John
person.setName('Jane');
console.log(person.getName()); // 출력: Jane
console.log(person.getAge()); // 출력: 30
예제 3: 메모이제이션
메모이제이션은 동일한 입력값에 대한 반복 계산을 피하기 위해 함수의 결과를 저장하는 최적화 기법이야.
이 예제에서는 memoize() 함수가 클로저를 사용하여 fn() 함수의 계산된 결과를 캐시에 저장해:
function memoize(fn) {
const cache = {};
return function(...args) {
const key = JSON.stringify(args);
if (cache[key]) {
return cache[key];
}
const result = fn(...args);
cache[key] = result;
return result;
};
}
function slowFunction(num) {
console.log('Computing...');
return num * 2;
}
const memoizedFunction = memoize(slowFunction);
console.log(memoizedFunction(5)); // 출력: Computing... 10
console.log(memoizedFunction(5)); // 출력: 10 (캐시에서 결과 가져옴)
GO TO FULL VERSION