JavaScriptクロージャ徹底解説!使い方10選とサンプルコード

JavaScriptクロージャのイメージJS
この記事は約7分で読めます。

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

この記事を読めば、JavaScriptのクロージャを使いこなすことができるようになります。

●クロージャとは

○クロージャの基本概念

クロージャとは、関数とその関数がアクセスできる外部変数をひとまとめにしたものです。

これにより、関数内で定義された変数が、関数の実行が終了しても保持されるようになります。

●クロージャの使い方

○サンプルコード1:カウンター機能

クロージャを使って簡単なカウンター機能を実装します。

function createCounter() {
  let count = 0;

  return function () {
    count++;
    console.log(count);
  };
}

const counter = createCounter();

counter(); // 1
counter(); // 2
counter(); // 3

○サンプルコード2:プライベート変数の実現

クロージャを利用してプライベート変数を実現します。

function createPerson(name, age) {
  let _name = name;
  let _age = age;

  return {
    getName: function () {
      return _name;
    },
    getAge: function () {
      return _age;
    },
  };
}

const person = createPerson("John Doe", 30);
console.log(person.getName()); // "John Doe"
console.log(person.getAge()); // 30

○サンプルコード3:イベントリスナーのスコープ

イベントリスナーでクロージャを利用し、変数のスコープを制限します。

document.querySelector("#button").addEventListener("click", (function () {
  let count = 0;

  return function () {
    count++;
    console.log("Button clicked " + count + " times.");
  };
})());

○サンプルコード4:タイマー機能

クロージャを使ってタイマー機能を実装します。

function createTimer() {
  let startTime = Date.now();

  return function () {
    const elapsedTime = Date.now() - startTime;
    console.log("Elapsed time: " + elapsedTime + "ms");
  };
}

const timer = createTimer();
setTimeout(() => {
  timer(); // Elapsed time: 経過時間(ms)が表示される
}, 1000);

○サンプルコード5:メモ化

クロージャを利用して、計算結果をキャッシュするメモ化を実装します。

function memoize(fn) {
  const cache = {};

  return function (arg) {
    if (cache[arg]) {
      return cache[arg];
    }

    const result = fn(arg);
    cache[arg] = result;
    return result;
  };
}

function factorial(n) {
  if (n === 0) {
    return 1;
  }
  return n * factorial(n - 1);
}

const memoizedFactorial = memoize(factorial);
console.log(memoizedFactorial(5)); // 120
console.log(memoizedFactorial(5)); // 120 (キャッシュから取得)

○サンプルコード6:モジュールパターン

クロージャを利用したモジュールパターンを実装します。

const myModule = (function () {
  let privateVar = "I am private.";

  function privateMethod() {
    console.log(privateVar);
  }

  return {
    publicMethod: function () {
      privateMethod();
    },
  };
})();

myModule.publicMethod(); // "I am private."

○サンプルコード7:一度だけ実行する関数

クロージャを使って、一度だけ実行される関数を作成します。

function createOnce(fn) {
  let called = false;

  return function () {
    if (!called) {
      called = true;
      return fn.apply(this, arguments);
    }
  };
}

const logOnce = createOnce(console.log);
logOnce("Hello!"); // "Hello!"
logOnce("Hello!"); // 何も表示されない

●クロージャの注意点と対処法

○メモリリークの対策

クロージャは、変数が保持され続けるため、メモリリークの原因になることがあります。

適切なタイミングでクロージャを解放することで、メモリリークを防ぐことができます。

●クロージャの応用例とサンプルコード

○サンプルコード8:デコレータパターン

クロージャを使ったデコレータパターンを実装します。

function withLogging(fn) {
  return function () {
    console.log("Executing " + fn.name);
    return fn.apply(this, arguments);
  };
}

function add(a, b) {
  return a + b;
}

const loggedAdd = withLogging(add);
console.log(loggedAdd(1, 2)); // "Executing add" と表示され、結果は 3

○サンプルコード9:イベントデリゲーション

クロージャを利用してイベントデリゲーションを実装します。

document.querySelector("#parent").addEventListener("click", function (event) {
  if (event.target.matches(".child")) {
    console.log("Child element clicked:", event.target);
  }
});

○サンプルコード10:スロットリング

クロージャを使ってスロットリングを実装します。

function throttle(fn, delay) {
  let lastCall = 0;

  return function () {
    const now = Date.now();
    if (now - lastCall >= delay) {
      lastCall = now;
      return fn.apply(this, arguments);
    }
  };
}

function onScroll() {
  console.log("Scroll event detected.");
}

window.addEventListener("scroll", throttle(onScroll, 500));

まとめ

この記事では、JavaScriptのクロージャについて初心者向けに解説し、10の使い方とサンプルコードを紹介しました。

クロージャを使いこなすことで、より効率的で保守性の高いコードを書くことができます。

ぜひこの記事を参考に、クロージャを活用したプログラミングを楽しんでください。