JavaScript 클로저: 루프에서 사용하는 간단한 실용적인 예

2024-04-10

JavaScript 클로저: 루프에서 사용하는 간단한 실용적인 예

문제

다음 코드를 살펴보세요.

for (var i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i); // 3, 3, 3 출력
  }, 1000);
}

이 코드는 3번 반복하며 각 반복마다 1초 후에 console.log(i)를 실행합니다. 하지만 예상과 달리 3번 모두 3이 출력됩니다. 그 이유는 각 콜백 함수가 실행될 때 i의 값이 이미 3으로 증가되었기 때문입니다.

클로저를 이용한 해결책

클로저를 사용하면 각 반복마다 i의 값을 제대로 출력할 수 있습니다. 다음 코드를 보세요.

for (var i = 0; i < 3; i++) {
  (function(i) {
    setTimeout(() => {
      console.log(i); // 0, 1, 2 출력
    }, 1000);
  })(i);
}

이 코드에서는 익명 함수를 사용하여 각 반복마다 새로운 클로저를 생성합니다. 클로저는 익명 함수의 스코프를 캡처하기 때문에 각 콜백 함수는 자신만의 i 값을 가지게 됩니다.

클로저의 장점

클로저를 사용하면 다음과 같은 장점을 얻을 수 있습니다.

  • 변수 캡처: 클로저는 함수 외부의 변수를 캡처하여 함수 내에서 사용할 수 있도록 합니다.
  • 데이터 은닉: 클로저는 외부 코드에서 내부 변수를 직접 접근하지 못하도록 하여 데이터 은닉을 가능하게 합니다.
  • 메모리 효율성: 클로저는 함수 스코프를 유지하기 때문에 메모리 효율성을 높일 수 있습니다.



예제 코드

// 1. 숫자 배열을 출력하는 예시

const numbers = [1, 2, 3];

const printNumbers = () => {
  for (const number of numbers) {
    // 클로저를 사용하여 각 숫자를 캡처
    (function(number) {
      setTimeout(() => {
        console.log(number); // 1, 2, 3 순서대로 출력
      }, 1000 * number);
    })(number);
  }
};

printNumbers();

// 2. 버튼 클릭 횟수를 출력하는 예시

let count = 0;

const button = document.getElementById("button");

button.addEventListener("click", () => {
  // 클로저를 사용하여 현재 클릭 횟수를 캡처
  (function(count) {
    setTimeout(() => {
      console.log(`클릭 횟수: ${count}`); // 클릭 순서대로 0, 1, 2, ... 출력
    }, 1000);
  })(count);

  count++;
});
  1. 숫자 배열을 출력하는 예시:

    • numbers 배열에 있는 각 숫자를 1초 간격으로 출력하는 예시입니다.
    • for 루프를 사용하여 배열을 순회하며 각 숫자를 캡처하는 클로저를 생성합니다.
    • setTimeout 함수를 사용하여 각 숫자를 1초 후에 출력합니다.
  2. 버튼 클릭 횟수를 출력하는 예시:

    • 버튼 클릭 횟수를 1초 간격으로 출력하는 예시입니다.
    • 클릭 이벤트 핸들러에서 클로저를 사용하여 현재 클릭 횟수를 캡처합니다.
    • setTimeout 함수를 사용하여 클릭 횟수를 1초 후에 출력합니다.

참고:

  • 클로저는 함수와 함수가 생성될 때의 렉시컬 환경(변수 스코프)의 조합입니다.
  • 클로저를 사용하면 함수 외부의 변수를 함수 내에서 사용할 수 있습니다.
  • 클로저는 데이터 은닉과 메모리 효율성을 높일 수 있습니다.



클로저 대체 방법

IIFE (즉시 실행 함수) 사용

for (var i = 0; i < 3; i++) {
  (function(i) {
    setTimeout(() => {
      console.log(i);
    }, 1000);
  })(i);
}

위 코드에서 (function(i) { ... })(i) 부분은 IIFE(즉시 실행 함수)입니다. IIFE는 함수를 선언하고 즉시 실행하는 방법입니다. IIFE를 사용하면 각 반복마다 새로운 함수 스코프가 생성되어 i 변수의 값을 제대로 캡처할 수 있습니다.

let 키워드 사용

for (let i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i);
  }, 1000);
}

위 코드에서 let 키워드를 사용하여 i 변수를 선언했습니다. let 키워드는 블록 스코프를 생성합니다. 즉, i 변수는 각 반복마다 새롭게 생성되어 클로저를 사용하는 것과 같은 효과를 얻을 수 있습니다.

화살표 함수 사용

for (var i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i);
  }, 1000);
}

위 코드에서 화살표 함수를 사용했습니다. 화살표 함수는 렉시컬 스코프를 사용하기 때문에 클로저를 사용하는 것과 같은 효과를 얻을 수 있습니다.

forEach 메서드 사용

const numbers = [1, 2, 3];

numbers.forEach(number => {
  setTimeout(() => {
    console.log(number);
  }, 1000 * number);
});

위 코드에서 forEach 메서드를 사용하여 배열의 각 항목을 순회합니다. forEach 메서드는 각 항목을 콜백 함수에 전달합니다. 콜백 함수는 각 항목을 1초 간격으로 출력합니다.

선택 가이드

어떤 방법을 사용할지는 상황에 따라 다릅니다.

  • 간단한 경우 IIFE 또는 let 키워드를 사용하는 것이 가장 간단합니다.
  • 함수를 재사용해야 하는 경우 클로저를 사용하는 것이 좋습니다.
  • 배열을 순회해야 하는 경우 forEach 메서드를 사용하는 것이 좋습니다.

참고:

  • IIFE는 익명 함수를 사용하기 때문에 코드를 읽기 어렵게 만들 수 있습니다.
  • let 키워드는 ES6에서 도입된 기능입니다.
  • 화살표 함수는 ES6에서 도입된 기능입니다.
  • forEach 메서드는 모든 배열에서 사용할 수 있습니다.

javascript loops closures


JavaScript, jQuery를 사용하여 브라우저 쿠키 읽기/쓰기

JavaScript는 웹 페이지에 동적 동작을 추가하는 데 사용되는 프로그래밍 언어입니다. 쿠키를 직접 읽고 쓰기 위해 JavaScript를 사용할 수 있지만, 이는 다소 복잡하고 오류 발생 가능성이 높습니다.jQuery는 JavaScript를 더욱 간편하게 사용할 수 있도록 돕는 JavaScript 라이브러리입니다...


자바스크립트 객체 배열에서 특정 속성 값을 추출하여 배열로 만드는 방법

map() 함수 사용:위 코드는 map() 함수를 사용하여 objects 배열의 각 객체에서 prop1 속성의 값을 추출하고 새로운 배열 newArray에 저장합니다. map() 함수는 배열의 각 요소를 처리하는 함수를 매개 변수로 받고...


HTML, CSS, 자바스크립트를 사용하여 문자 절반에 CSS 적용하기 (가능한가?)

가짜 문자 사용:두 개의 가짜 문자를 만들어 하나는 원하는 CSS를 적용하고, 다른 하나는 투명하게 만듭니다.두 가짜 문자를 나란히 배치하여 원하는 문자처럼 보이게 합니다.CSS 글리터 사용:CSS 글리터를 사용하여 문자의 절반을 덮는 형태의 가짜 문자를 만듭니다...


React 변수 문(JSX)을 사용하여 HTML 삽입

위 예시에서는 name 변수에 문자열 "김민수"를 할당하고, greeting 변수에는 <h1> 태그 안에 name 변수를 포함하는 JSX 표현식을 할당합니다. 마지막으로 ReactDOM. render 함수를 사용하여 greeting 변수를 root ID를 가진 DOM 요소에 렌더링합니다...


JavaScript, ReactJS, ESLint에서 발생하는 "ESLint Parsing error: Unexpected token" 오류 해결

오류 원인:코드 구문 오류: JavaScript, ReactJS 코드에 문법 오류나 누락된 괄호, 따옴표 등이 있을 경우 ESLint는 해당 토큰을 예상하지 못한 위치에서 발견하여 "Unexpected token" 오류를 발생시킵니다...


javascript loops closures