Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

関数実行の裏側では何が起きているのか?

Avatar for minop1205 minop1205
November 27, 2025

 関数実行の裏側では何が起きているのか?

2025年11月27日のイベント「プロによる本気の攻略本『JavaScript/TypeScript実力強化書』 - FL#115」で発表した内容です。

JavaScriptのスコープ規則である「レキシカルスコープ」、そしてそのレキシカルスコープの内部機構である、レキシカル環境とクロージャについてのまとめです。

Avatar for minop1205

minop1205

November 27, 2025
Tweet

Other Decks in Programming

Transcript

  1. 関数 foo の 定義位置 から見た外部変数 x の値は global 関数 foo

    の 実行位置 から見た外部変数 x の値は local 外部変数 x の値を出力 A B A B の出力結果は? レキシカルスコープ
  2. JavaScriptの関数は 第1級関数 なので、 関数の戻り値にすることができる 入れ子型の関数の場合はどうなるか? 変数 fn には outer 関数の実行結果(=

    inner 関数)が入る A A の出力結果は? • inner 関数はコード上では outer 関数のローカル変 数 x を参照している • inner 関数実行のタイミングでは outer 関数の実行 は終了している
  3. 結果は outer と出力される outer 関数の実行終了後も その スコープは保持されている inner 関数実行時、outer 関数の実行は終了しているが

    outer 関数のローカル変数 x は依然として参照できている 入れ子型の関数の場合はどうなるか?
  4. 関数が参照するスコープ(外側の関数のスコープ)を保持する仕組みが必要 この仕組みを支えるのが レキシカル環境 と クロージャ JavaScriptの関数は 第1級オブジェクト なので、定義時のスコープとは異なるス コープ上に持ち出して実行できる JavaScriptは

    レキシカルスコープ なので、関数から見たスコープはコード上 の位置によって静的に決定される 関数はどこにでも持ち出せるが あくまで定義場所から見たスコープで実行される
  5. レキシカル環境 (Lexical Environment) • レキシカル環境 (または単に環境と言ったりする)は、コードブロックに処理が移った時に作られる特 殊なオブジェクト • レキシカル環境は、そのブロックで宣言された変数(または関数)と値の対応表である環境レコード (Environment

    Record)と、外側の環境への参照 (Outer Environment )をセットにしたもの • レキシカル環境は、ブロックに処理が移ったタイミングで都度作成される。 Lexical Environment Environment Record Outer Environment
  6. ① グローバルスコープのレキシカル環境 { foo: “foo” } Environment Record null Outer

    Environment ② ブロックコープのレキシカル環境 { bar: “bar” } Environment Record ① への参照 Outer Environment ③ ブロックコープのレキシカル環境 { baz: “baz” } Environment Record ② への参照 Outer Environment × スコープ チェーン ブロックスコープのレキシカル環境
  7. ① グローバルスコープのレキシカル環境 { foo: Closure(foo, ①), fn: undefined } Environment

    Record null Outer Environment • レキシカル環境が作られた後、そこに属する関数はクロージャ (Closure)になる。 • クロージャは、関数および自身が属するレキシカル環境への参 照をセットにしたもの 関数スコープのレキシカル環境
  8. ① グローバルスコープのレキシカル環境 { foo: Closure(foo, ①) , fn: undefined }

    Environment Record null Outer Environment ② foo スコープのレキシカル環境 { color: “red”, bar: Closure(bar, ②) } Environment Record ① への参照 Outer Environment • クロージャを実行すると、対応する関数スコープのレキシカル 環境が新たに作られる • 生成されたレキシカル環境は、クロージャが保持している「レキ シカル環境への参照」を Outer Environmentに登録する 関数スコープのレキシカル環境
  9. ① グローバルスコープのレキシカル環境 { foo: Closure(foo, ①), fn: Closure(bar, ②) }

    Environment Record null Outer Environment ② foo スコープのレキシカル環境 { color: “red”, bar: Closure(bar, ②) } Environment Record ① への参照 Outer Environment • 外側の関数が、内部の関数をリターンする場合、実際には 内部の関数(=クロージャ)へのリンクが返される barクロージャへのリンクが格納される 関数スコープのレキシカル環境
  10. ① グローバルスコープのレキシカル環境 { foo: Closure(foo, ①), fn: Closure(bar, ②) }

    Environment Record null Outer Environment ② foo スコープのレキシカル環境 { color: “red”, bar: Closure(bar, ②) } Environment Record ① への参照 Outer Environment ③ bar スコープのレキシカル環境 {} Environment Record ② への参照 Outer Environment 関数スコープのレキシカル環境
  11. • 環境は他の環境から参照されている間は削除されない • そのため foo の実行終了後もその内部変数は参照可能 関数スコープのレキシカル環境 ① グローバルスコープのレキシカル環境 {

    foo: Closure(foo, ①), fn: Closure(bar, ②) } Environment Record null Outer Environment ② foo スコープのレキシカル環境 { color: “red”, bar: Closure(bar, ②) } Environment Record ① への参照 Outer Environment ③ bar スコープのレキシカル環境 {} Environment Record ② への参照 Outer Environment
  12. データのカプセル化 ① グローバルスコープのレキシカル環境 { createCounter: Closure(createCounter, ①), counter: undefined }

    Environment Record null Outer Environment ② createCounter スコープのレキシカル環境 { count: 0, counter: Closure(counter, ②) } Environment Record ① への参照 Outer Environment ③ counter スコープのレキシカル環境 {} Environment Record ② への参照 Outer Environment ④ counter スコープのレキシカル環境 {} Environment Record ② への参照 Outer Environment ⑤ counter スコープのレキシカル環境 {} Environment Record ② への参照 Outer Environment counter を実行する度に count が更新されていく (よくあるカウンターの例)
  13. カリー化 (バリデーション関数のカリー化例) ① グローバルスコープのレキシカル環境 { minLength: Closure(minLength, ①), min3: undefined,

    min8: undefined } Environment Record null Outer Environment ② minLength スコープのレキシカル環境 { len: 3, validate: Closure(validate, ②) } Environment Record ① への参照 Outer Environment ③ minLength スコープのレキシカル環境 { len: 8, validate: Closure(validate, ③) } Environment Record ① への参照 Outer Environment ④ validate スコープのレキシカル環境 { value: ”hi” } Environment Record ② への参照 Outer Environment ⑤ validate スコープのレキシカル環境 { value: ”hello” } Environment Record ② への参照 Outer Environment ⑥ validate スコープのレキシカル環境 { value: ”12345” } Environment Record ③ への参照 Outer Environment