javaとjavascriptの違い

未分類
function createCounter() {
  let count = 0;  // 外側の変数
  return function() {  // 内側の関数
    count++;
    return count;
  };
}

let counter = createCounter();
Logger.log(counter());  // 出力: 1
Logger.log(counter());  // 出力: 2
Logger.log(counter());  // 出力: 3

というか、これですがjavaの場合はメソッド毎にデータが保持されないので、値は変わらないと思うのですが、javascriptの場合、値が順にふえていくのはどうしてですか?

クロージャとは?

クロージャとは、関数が宣言されたときのスコープ(範囲)を保持する機能のことです。JavaScriptでは、関数が別の関数内で宣言されると、その外側の関数の変数にアクセスでき、そのスコープを保持し続けます。これにより、関数が外部で実行される際にも、元のスコープの変数(この場合、count)にアクセスし、それを操作できるのです。

具体的には、以下のように動作します:

  1. createCounter関数が呼び出されると、countというローカル変数が初期化されます (let count = 0;)。
  2. createCounter関数は、countにアクセスできる無名関数を返します。この無名関数は、count++を実行することでカウントを増加させます。
  3. 返された無名関数は、そのスコープで**count変数の参照を保持**します。つまり、createCounter関数が終了した後でも、countにアクセスし、値を操作できるのです。
  4. counter()を呼び出すたびに、count++が実行され、countの値が順に増加していきます。

JavaとJavaScriptの違い

Javaでは、メソッドが呼ばれるたびにローカル変数は再初期化され、メソッドが終了するとそのスコープの変数は破棄されます。したがって、Javaでは以下のようなコードを書いても、変数countは毎回初期化され、値を保持し続けることはありません。

Javaでは、例えば次のように書くと、countは毎回0からスタートします。

javaコードをコピーするpublic class Counter {
    public int createCounter() {
        int count = 0;  // 外側の変数
        count++;
        return count;
    }

    public static void main(String[] args) {
        Counter counter = new Counter();
        System.out.println(counter.createCounter());  // 出力: 1
        System.out.println(counter.createCounter());  // 出力: 1
    }
}

JavaScriptで値が保持される理由:クロージャの仕組み

JavaScriptでは、関数内で別の関数を返すと、その外側の関数のスコープが保持されます。具体的には、以下の流れです。

  1. createCounter関数が実行されると、count変数が定義されます(初期値0)。
  2. createCounterは、countをインクリメントする関数を返しますが、その関数は**countのスコープを保持**します。
  3. let counter = createCounter();により、counter変数には、countにアクセスできる関数が格納されます。
  4. counter()を呼び出すたびに、そのスコープ内のcountがインクリメントされます。

重要なのは、createCounterが終了した後でも、countが保持されることです。これがクロージャの効果です。

クロージャの仕組み:図解

  1. createCounter()呼び出し
    • count変数が0で初期化され、count++を実行する無名関数が返される。
  2. counter()の呼び出し
    • count変数がインクリメントされ、1になる。
    • counter()の呼び出しごとに、同じcountが保持され、値が増加する。

JavaScriptでは、このように関数が定義された時点の**スコープ(環境)**を保持することで、変数が後から呼び出された関数の中で保持され続け、更新されていくわけです。

まとめ

  • クロージャとは、関数がその外側のスコープにある変数を保持し続ける仕組みのことです。これにより、countのようなローカル変数を外部の関数から操作することが可能です。
  • Javaでは、メソッドを呼び出すたびにローカル変数は再初期化されますが、JavaScriptではクロージャにより、関数が変数のスコープを保持するため、値が保持されて更新され続けます。

この動作が、JavaScriptが関数を第一級オブジェクトとして扱い、柔軟にスコープを管理できるという強力な機能の一つです。

コメント

タイトルとURLをコピーしました