[매일코딩] 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)이 생성된다. 이 때문에 참조 값이 기록된다.

이해하기 참 어렵습니다. 하지만 많은 예제를 접하다 보면 언젠가는 아 ~ !! 라고 말 할 수 있을 날이 올 것 입니다. ㅜㅜ

Sort:  

@wonsama transfered 2.7 KRWP to @krwp.burn. voting percent : 94.92%, voting power : 1740, voting power : 1794057.15, SBD KRW : 1223.21.

Coin Marketplace

STEEM 0.19
TRX 0.17
JST 0.030
BTC 82470.22
ETH 3177.63
USDT 1.00
SBD 2.82