[JavaScript ES6] Closure

Sooooooah·2023년 4월 25일

javaScript ES6

목록 보기
6/8

6. 클로저(Closure)


클로저란?

외부에 있는 변수가 내부에 있는 함수와 함수 호출 후에도 종료되지 않고 계속 참조하는 것

1. 바깥쪽에 있는 함수의 변수를 내부 함수가 참조

const external = () => {
  let number = 65; // 아스키코드 65 > A
  let internal = () => {
    let char_ = String.fromCharCode(number);
    console.log(char_, number++); // internal 함수 내부에는 number가 없으므로 상위로 올라가서 number를 찾음
    console.log(number); // 66
  };
  internal();
};

external(); // A 65
external(); // B 66 X >> A 65

2. return

const external2 = () => {
  let number = 65;
  let internal = () => {
    let char_ = String.fromCharCode(number);
    return `${char_} : ${number++}`;
  };
  return internal();
};

console.log(external2()); // A : 65
console.log(external2()); // B : 66 X > A : 65

3. 클로저 생성

const out = function () {
  let number = 65;
  let internal = function () {
    let char_ = String.fromCharCode(number);
    return `${char_} : ${number++}`;
  };
  // return internal(); --> 함수값을 반환
  return internal; //   --> 함수 자체를 반환, 리턴값을 가진채로 밖으로 호출
};

// 리턴된 함수를 변수에 넣어서 재실행
const outRe = out();

console.log(outRe()); // A 65
console.log(outRe()); // B 66
console.log(outRe()); // C 67
console.log(outRe()); // D 68

1초 단위로 1씩 증가하는 클로저 카운터 구현하기

const out = () => {
  let cnt = 0;
  let internal = () => ++cnt;
  return internal;
};

const outRe = out();

setInterval(() => console.log(outRe()), 1000);

버튼 클릭시 클로저 카운팅

// index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      button {
        background: #000;
        border: none;
        color: #fff;
        padding: 15px 32px;
        text-align: center;
        font-size: 16px;
      }
      p {
        font-size: 64px;
        text-align: center;
      }
    </style>
  </head>
  <body>
    <button id="btnView" class="btn">+</button>
    <p id="cntView">0</p>
    <script src="es6.js"></script>
  </body>
</html>
// app.js
const btnView = document.getElementById("btnView");
const cntView = document.getElementById("cntView");

const out = () => {
  let cnt = 0;
  let internal = () => ++cnt;
  return internal;
};

const outRe = out();

btnView.onclick = () => {
  cntView.innerText = outRe();
};

li 리스트 태그에서의 클로저와 let

const li = document.querySelectorAll("li");

for (var i = 0; i < li.length; i++) {
  console.log(i);
  li[i].addEventListener("click", () => console.log(i + "번째 아이템입니다."));
}

무엇을 클릭하던 '4번째 아이템입니다.' 출력
i 값이 이벤트 콜백함수 내에서 외부의 var로 선언되어져 있는 i를 참조하는게 문제(호이스팅된 var)
—> 재할당이 가능하면서 블록 스코프 변수인 let 사용

for (let i = 0; i < li.length; i++) {
  console.log(i);
  li[i].addEventListener("click", () =>
    console.log(i + 1 + "번째 아이템입니다.")
  );
}

리스트 함수로 만들어 자동화하기

const makeList = (arr) => {
  let el = "<ul>\n";
  for (let i = 0; i < arr.length; i++) {
    el += "<li>" + arr[i] + "</li>\n";
  }
  el += "</ul>";
  return el;
};

const animals = ["사자", "호랑이", "하마", "악어", "개", "고양이", "코끼리"];
const li_Items = makeList(animals);

document.body.innerHTML = li_Items;

// Click Event
const li = document.querySelectorAll("li");

for (let i = 0; i < li.length; i++) {
  li[i].addEventListener("click", () => console.log(i + "번째 요소"));
}
profile
즐거운 서비스를 추구합니다.

0개의 댓글