[매일코딩] 002 - 자바스크립트 클로저
출처
https://www.freecodecamp.org/news/javascript-closure-tutorial-with-js-closure-example-code/
클로저 ( closure )
많은 JavaScript 개발자들이 이 용어를 들어 본 적이있을 것입니다. 말 그대로 close 닫쳐진 상태에서 동작하는 함수인데 Javascript 에서 가장 중요하고 흥미로운 개념 중 하나라 생각 합니다.
어휘적 범위 ( lexical scoping )
아래 함수를 보면 내부 함수(greetingMsg)에서 외부에 선언된 변수(customerName)에 접근할 수 있는 것을 볼 수 있습니다. 이것은 어휘 범위(lexical scoping) 입니다. 변수의 범위와 값은 변수가 정의 또는 생성 된 위치 (즉, 코드에서의 위치)에 의해 결정됩니다.
function greetCustomer() {
var customerName = "anchal";
function greetingMsg() {
console.log("Hi! " + customerName); // Hi! anchal
}
greetingMsg();
}
아래 함수(greetingMsg)를 보면 customerName에 접근할 수 없어서 참조오류 (ReferenceError)가 발생하는 것을 볼 수 있습니다. 두개의 함수 (greetingMsg, greetCustomer)가 별도로 지정되어 있기 때문 입니다.
function greetingMsg() {
console.log(customerName);// ReferenceError: customerName is not defined
}
function greetCustomer() {
var customerName = "anchal";
greetingMsg();
}
greetCustomer();
아래 함수도 보면 addNumbersGenerate 함수에서 addNumbers 함수로 number2 의 값을 전달하여 정상적으로 처리 될 것 같아 보이지만, 실제로는 addNumbers 함수로는 값이 전달되기 때문에 (c 언어 등의 참조 포인터가 아님에 유의) addNumbers 함수 기준으로 보면 number2 가 정의 되지 않아서 참조오류가 발생하게 됩니다.
function addNumbers(number1) {
console.log(number1 + number2);
}
function addNumbersGenerate() {
var number2 = 10;
addNumbers(number2);
}
addNumbersGenerate();
아래 예제를 살펴보면 결과 값은 12가 출력되게 됩니다. addNumbersGenerate 함수 내부에서 10을 addNumbers 함수로 전달하고 addNumbers 내부의 저의되지 않은 number2 값은 전역영역(global)에 2로 정의되어 있기 때문에 10 + 2 = 12를 출력하게 됩니다.
var number2 = 2;
function addNumbers(number1) {
console.log(number1 + number2);
}
function addNumbersGenerate() {
var number2 = 10;
addNumbers(number2);
}
addNumbersGenerate();
그렇다면 클로저란 ?
내부 함수가 외부 함수 변수 및 인수에 액세스 할 수있을 때 클로저가 작성됩니다.
아래 함수와 같이 함수 속에 또 다른 함수가 정의 되고 내부 함수(greetingMsg)에서는 외부에 정의 된 상수(customerName)를 접근할 수 있습니다. 하지만 외부 함수(greetCustomer) 밖에서는 외부 함수 내부에 정의된 상수(customerName)에 접근 할 수 없게 됩니다.
또한 주요 특징으론 내부 함수의 변수 등의 값은 유지가 된다는 점입니다.
function greetCustomer() {
const customerName = "anchal";
function greetingMsg() {
console.log("Hi! " + customerName);
}
return greetingMsg;
}
const callGreetCustomer = greetCustomer();
callGreetCustomer(); // output – Hi! anchal
아래 예를 보면 좀더 손쉽게 와 닿을 수 있습니다.
countValue를 호출 할 때마다 카운트 변수 값이 1 씩 증가합니다. ( count 값이 0이라고 생각하십니까? )
클로저는 값과 함께 작동하지 않기 때문에 그것은 잘못된 것입니다. 변수의 참조를 저장합니다. 그렇기 때문에 값을 업데이트 할 때 클로저가 참조를 저장함에 따라 두 번째 또는 세 번째 호출 등에 반영됩니다.
function counter() {
let count = 0;
return function() {
return count++;
};
}
const countValue = counter();
countValue(); // 0
countValue(); // 1
countValue(); // 2
하나의 예를 더 보면, 아래와 같이 값이 저장되어 기록되는 것을 확인할 수 있습니다.
function addNumber(number1) {
return function (number2) {
return number1 + number2;
};
}
const addNumberCall = addNumber(7);
addNumberCall(8) // 15
addNumberCall(6) // 13
맺음말
클로저는 이것만 기억하면 좋습니다. 내부 변수값이 별도 영역(scope)이 생성된다. 이 때문에 참조 값이 기록된다.
이해하기 참 어렵습니다. 하지만 많은 예제를 접하다 보면 언젠가는 아 ~ !! 라고 말 할 수 있을 날이 올 것 입니다. ㅜㅜ
@wonsama transfered 2.7 KRWP to @krwp.burn. voting percent : 94.92%, voting power : 1740, voting power : 1794057.15, SBD KRW : 1223.21.