ECMAScript仕様輪読会 #61
前回: ECMAScript仕様輪読会 #60
21:14 再開
Scrapboxの招待リンク: https://scrapbox.io/projects/esspec/invitations/85b96c9fa718ce5185e307196ed8fb53
connpass: https://esspec.connpass.com/
Discord: https://discord.gg/59S3y6weQj
ES Spec Draft: https://tc39.es/ecma262/
読み物リスト
Twitter hashtag: #esspec
便利ツール
esspec-memo: https://tars0x9752.github.io/esspec-memo/esspec.html
Scrapbox Codeblock Generator: https://vzvu3k6k.github.io/scrapbox-codeblock/
TC39 Terminology: https://github.com/tc39/how-we-work/blob/main/terminology.md
時事ネタ
ES2024がリリースされました🎉
自己紹介 (近況報告)
syumai syumai.icon
Twitter: https://twitter.com/__syumai GitHub: https://github.com/syumai
Go / TSを書いて暮らしてます
iwatsurut
とくに、イベントもなく過ごしています。
前回のあらすじ
今回の範囲
全体の復習
Note 1
FunctionDeclarationInstantiationを通して作られるEnvironment Recordの数
formal parametersに初期化子がある
2つ
formal parameters用
body declarations用
formal parametersに初期化子がない
1つ
formal parametersおよびbody declarations用
ExecutionContext (calleeContext) が作られているのは、Function Objectの [[Call]] internal method内
https://tc39.es/ecma262/#sec-ecmascript-function-objects-call-thisargument-argumentslist
calleeContextのEnvironmentRecordは [[Call]] internal method内の PrepareForOrdinaryCall で作っている
https://tc39.es/ecma262/#sec-prepareforordinarycall
arguments Objectの初期化について
第56回に詳しいサンプルコードあり
step 19, 20で、If strict is true or hasParameterExpressions is false の条件が必要な理由
strict modeではないdirect evalが、新たなEnvironmentRecordを作らず、実行中のExecutionContextのVariableEnvironmentに対して束縛を作成するため
code:js
function f1() {
eval("var a = 1;");
console.log(a);
}
function f2() {
"use strict";
eval("var a = 1;");
console.log(a);
}
f1();
f2();
要確認ポイント
下記の2つのevalの振る舞いの違いについて
strict mode下でないとき、direct evalは新しいEnvironment Recordを導入しない
Function Objectの [[Call]] internal methodの呼び出しは、呼び出し元のExecution ContextのEnvironment RecordをOuterEnvとして新たなEnvironment Recordを作成する
→Function Object自身が持つ [[Environment]] internal slotをOuterEnvとして、新たなEnvironment Recordを作成する
→この時、f2()内のxをf1()のevalが参照するか?
code:js
function f1(_ = eval("x = 2")) {
console.log("inside", x);
}
function f2() {
var x = 1;
f1();
console.log("outside", x);
}
f2();
// inside 2
// outside 1
code:js
function f(_ = eval("x = 2")) {
console.log("inside", x);
}
var x = 1;
f();
console.log("outside", x);
// inside 2
// outside 2
code:js
function f1(_ = eval("x = 2")) {
var x = 3;
console.log("inside", x);
}
function f2() {
var x = 1;
f1();
console.log("outside", x);
}
f2();
console.log("global", x);
// inside 3
// outside 1
// global 2
code:js
function f1(_ = eval("x = 2"), x = 3) {
console.log("inside", x);
}
function f2() {
var x = 1;
f1();
console.log("outside", x);
}
f2();
// ReferenceError: Cannot access 'x' before initialization
code:js
function f1(x = 3, _ = eval("x = 2")) {
console.log("inside", x);
}
function f2() {
var x = 1;
f1();
console.log("outside", x);
}
f2();
// inside 2
// outside 1
Environment Recordの一覧
global
f2のbody
f1のbody
f1のパラメータ
Environment Recordの階層構造
f2のbody: global -> f2のbody
f1のパラメータ: global -> f1のパラメータ
f1のbody: global -> f1のパラメータ -> f1のbody
evalの評価に使われるEnvironment Record
f1のパラメータのEnvironment Record