function secretCode() {
let secret = '123';
return function() {
return secret;
};
}
let getCode = secretCode();
console.log(getCode()); // "123"
비밀번호, API 키, 데이터베이스 연결 문자열 등과 같은 민감한 정보를 숨기는 데 사용됩니다. 이런 정보들은 클라이언트 측 코드에 직접 포함되면 보안 위험이 있습니다. 클로저를 사용하면 이런 정보를 함수 스코프 내에서만 접근 가능하게 만들어 외부에서는 직접적으로 접근할 수 없게 합니다.
function counter() {
let count = 0;
return function() {
return ++count;
};
}
let increment = counter();
console.log(increment()); // 1
console.log(increment()); // 2
상태 유지는 웹 페이지나 어플리케이션에서 일반적으로 발생하는 시나리오입니다. 예를 들어, 웹 페이지에서 특정 버튼의 클릭 횟수를 추적하거나, 게임에서 플레이어의 점수를 계속 추적하는 등의 작업에 클로저를 사용할 수 있습니다.
function multiplier(factor) {
return function(num) {
return num * factor;
};
}
let double = multiplier(2);
console.log(double(5)); // 10
함수 팩토리 패턴은 여러 종류의 유사한 함수를 생성할 필요가 있을 때 유용합니다. 예를 들어, 환율 변환기에서 서로 다른 환율을 적용하는 여러 함수를 생성할 수 있습니다.
let calculator = (function() {
let data = { number: 0 };
return {
add: function(num) {
data.number += num;
},
subtract: function(num) {
data.number -= num;
},
display: function() {
console.log(data.number);
}
};
})();
calculator.add(5);
calculator.display(); // 5
JavaScript에서는 모듈 패턴을 사용하여 코드를 여러 파일로 분할하고 네임스페이스를 관리할 수 있습니다. 이를 통해 코드를 재사용하고 관리하기 쉽게 만들 수 있습니다. 클로저를 사용하면 모듈 내의 변수를 은닉하고, 오직 모듈 내부에서만 접근 가능하게 할 수 있습니다.
for(var i = 0; i < 5; i++) {
(function(index) {
setTimeout(function() {
console.log(index + 1); // 1, 2, 3, 4, 5
}, 1000);
})(i);
}
JavaScript에서 비동기 이벤트를 처리하기 위해 이벤트 핸들러와 콜백을 사용하는 것이 일반적입니다. 클로저는 이벤트 핸들러 또는 콜백이 생성된 환경을 "기억"하게 하여, 이벤트나 콜백이 발생했을 때 필요한 모든 정보에 접근할 수 있도록 합니다.
function greet(greeting) {
return function(name) {
console.log(`${greeting}, ${name}`);
};
}
let greetInEnglish = greet("Hello");
greetInEnglish("John"); // "Hello, John"
커링은 함수를 더 작은 함수로 분해하는 프로그래밍 패턴입니다. 각각의 함수는 한 개의 인수만을 받습니다. 이 패턴은 코드의 재사용성을 높이며 가독성을 향상시키는데 도움이 됩니다. 예를 들어, 특정 유형의 로그 메시지를 작성하는 여러 함수를 생성할 수 있습니다.
function greaterThan(n) {
return function(m) {
return m > n;
};
}
let greaterThan10 = greaterThan(10);
console.log(greaterThan10(11)); // true
데이터를 조작하는 함수를 생성하는 경우에 클로저를 사용할 수 있습니다. 예를 들어, 배열의 filter, map, reduce와 같은 고차 함수에 전달될 콜백 함수를 생성하는 데 클로저를 사용할 수 있습니다.
function handleFile(file) {
let fileReader = new FileReader();
fileReader.onload = function() {
// 파일 핸들링
};
fileReader.onclose = function() {
// 클로저를 사용하여 리소스 정리
};
fileReader.readAsArrayBuffer(file);
}
외부 리소스를 사용하는 함수는 종종 클린업 작업을 필요로 합니다. 예를 들어, 파일을 열고 데이터를 읽은 후, 파일을 닫아야 할 수 있습니다. 클로저를 사용하면 함수가 리소스를 사용하는 동안 리소스를 보호하고, 함수가 종료될 때 클린업 코드를 실행할 수 있습니다.
function memoize(fn) {
let cache = {};
return function(n) {
if (n in cache) {
console.log('Fetching from cache');
return cache[n];
}
else {
console.log('Calculating result');
let result = fn(n);
cache[n] = result;
return result;
}
};
}
const factorial = memoize(
x => {
if (x === 0) {
return 1;
}
else {
return x * factorial(x-1);
}
}
);
console.log(factorial(5)); // calculated
console.log(factorial(5)); // fetched from cache
메모이제이션은 함수의 결과를 저장하여 불필요한 계산을 줄이는 기법입니다. 이는 계산 비용이 큰 함수를 최적화하는 데 유용합니다. 클로저를 사용하면 함수의 결과를 함수 외부에 저장하고, 다음에 동일한 인수로 함수가 호출될 때 저장된 결과를 반환할 수 있습니다.
const bankAccount = (initialBalance => {
let balance = initialBalance;
return {
getBalance: function() {
return balance;
},
deposit: function(amount) {
balance += amount;
return balance;
},
};
})(0);
console.log(bankAccount.getBalance()); // 0
console.log(bankAccount.deposit(200)); // 200
JavaScript 클래스는 특별히 프라이빗 필드를 지원하지 않지만, 클로저를 사용하면 이를 모방할 수 있습니다. 클로저를 사용하면 클래스의 인스턴스 변수를 외부에서 접근하지 못하게 만들 수 있습니다. 이를 통해 클래스의 상태를 보호하고 불필요한 변경으로부터 보호할 수 있습니다.