JavaScriptでのクロージャ

Mar 18 2023
Closure とは何ですか?実際にいつ使用できるようになりますか? Closure を理解するには、JavaScript の 2 つの単純な概念、入れ子関数と関数を返すことについて知る必要があります。ネストされた関数 JavaScript では、ネストされた関数を使用できます。

Closure とは何ですか?実際にいつ使用できるようになりますか?

Closure を理解するには、JavaScript の 2 つの単純な概念、入れ子関数と関数を返すことについて知る必要があります。

入れ子関数

JavaScript では、関数を入れ子にすることができます。内部関数は、外部関数の変数とパラメーターにアクセスできます。

次の例を確認してみましょう。

function greetPerson(name) {
  const message = 'Hello';
  
  function displayMessage() {
    console.log(`${message} ${name}!`);
  }

  displayMessage();
}

greetPerson('Alex'); // Hello Alex!

関数を返す

外部関数内で内部関数を宣言して呼び出すだけでなく、外部から呼び出せるように内部関数を返すこともできます。

この例を見てみましょう:

function greetPerson(name) {
  const message = 'Hello';
  
  function displayMessage() {
    console.log(`${message} ${name}!`);
  }

  return displayMessage;
}

const displayMessageFunction = greetPerson('Alex');

console.log(typeof(displayMessageFunction)); // function
displayMessageFunction(); // Hello Alex!

閉鎖

この 2 つの概念を理解すると、クロージャの「定義」は非常に簡単になります。

クロージャとは、外部関数が戻った後でも、内部関数がその外部関数の変数とパラメーターにアクセスできることを意味します。

クロージャがどのように使用できるかを正確に確認できる別の例を見てみましょう。

function counterFunction() {
 let counter = 0;

 function increaseCounter() {
  return counter += 1;
 }

 return increaseCounter;
}

// counter reffers to the increaseCounter returned by the counterFunction
const counter = counterFunction();

console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
console.log(counter()); // 4

内部関数は外部変数の個別のコピーを保持しませんが、外部変数を参照します。つまり、counterinner 関数を使用して の値を変更すると、 の値も変更されます。

外側の関数は内側の関数counterFunctionへの参照も返すincreaseCounterため、それを呼び出すと、counter変数の実際の値が変更されます。counterこのようにして、呼び出しのたびに変数の値が新しく増加していることがわかりますcounter()。

クロージャをいつ使用するか?

クロージャを使用して JavaScript でカプセル化を実現できます。これは、詳細な実装を非表示にすることで実現できます。このようにして、プライベート変数と関数を作成できます。

次の例を確認してみましょう。ここでは、関数とオブジェクトのみを使用して一部のデータをカプセル化します。

const counter = (function () {
  let privateCounter = 0;

  function changeBy(val) {
    privateCounter += val;
  }

  function increaseCounter() {
    changeBy(1);
  }

  function decreaseCounter() {
    changeBy(-1);
  }

  function decreaseCounter() {
    return privateCounter;
  }

  return { increaseCounter, decreaseCounter, getCounterValue };
})();

console.log(counter.getCounterValue()); // 0

counter.increaseCounter();
counter.increaseCounter();

console.log(counter.getCounterValue()); // 2

counter.decreaseCounter();

console.log(counter.getCounterValue()); // 1

increaseCounterと を呼び出すだけで外部からカウンタの値を制御でき、ゲッターのように動作する関数をdecreaseCounter呼び出すことで値を取得できます。getCounterValue

このようにして、指定子publicとprivateアクセス指定子をシミュレートし、カプセル化を実現できます。

これは、プライベートにしておくべき変数や関数に対する意図しない変更を防ぐため、ソフトウェア開発において非常に強力な概念です。

それで全部です!

JavaScript のクロージャに関するこの記事をお読みいただき、ありがとうございます。この重要な概念と、それを使用してカプセル化を実現し、プライベート変数や関数を作成する方法をよりよく理解するのに役立つことを願っています。