JavaScriptのクロージャと関数オブジェクトのお話を聞く機会があり、自分なりに整理してみた
先に関数オブジェクトについてまとめていたとき
関数オブジェクトは「実行時にname
とlength
をもったオブジェクトが作られる」とイメージするのが良さそうとなった
だが、実際は普通のオブジェクトでは説明ができない
例えば、以下のように外側のスコープにある変数・引数を参照するため、関数オブジェクトは自身の「環境」を知っている
let x = 1 function f (y) { const z = x + y return z }
他にも、関数オブジェクトは関数本体を知っていたりと、ただのオブジェクトにはないプロパティが存在する
内部スロット
これを説明するために内部スロットというものを知る必要がある
これは
・ECMAScriptの仕様にだけ現れるプロパティのようなもの
・JSの実行中には存在しない
・処理系(v8)にこういうのがあると考えると便利
・そのとおりに実装されているとは限らない
・通常のプロパティと区別するため二重ブラケットで囲む[[]]
関数オブジェクトの内部スロット
11個定義されている(ES2020)
https://tc39.es/ecma262/#sec-ecmascript-function-objects
[[Enviroment]]
- 環境を包む「環境」への参照
- EnvironmentRecord型
- https://tc39.es/ecma262/#sec-environment-records
- 環境内の変数や引数とその値の束縛を (複数) 保持する
- 外側の環境を参照する
[[OuterEnv]]
を持つ
[[ECMAScriptCode]]
- 関数本体 (ボディ) への参照
関数オブジェクトの裏側には内部スロットがあって、それらが自身の「環境」や関数本体が知る理由であることがわかった