JavaScript プログラムは、ステートメントと関数宣言で構成されます。JavaScript プログラムが実行されると、次の 2 つのステップが実行されます。
コードが関数宣言のためにスキャンされ、すべての関数宣言が「実行」され(関数オブジェクトを作成することによって)、その関数への名前付き参照が作成されます(この関数をステートメント内から呼び出すことができるように)。
文は(コードに表示されているとおりに)順番に実行(評価)されます。
そのため、この問題なく動作します:
<script>
foo();
function foo() {
return;
}
</script>
「foo」関数は宣言される前に呼び出されますが、関数宣言がステートメントの前に評価されるため機能します。
しかし、この動作しません:
<script>
foo();
</script>
<script>
function foo() {
return;
}
</script>
ReferenceError がスローされます ("foo が定義されていません")。これにより、Web ページの HTML コード内のすべての SCRIPT 要素が個別の JavaScript プログラムを表し、HTML パーサーが SCRIPT 要素に遭遇するたびに、その要素内のプログラムが実行されるという結論が導き出されます (プログラムが実行されると、パーサーは SCRIPT 要素に続く HTML コードに進みます)。
ところで、これは動作する:
<script>
function foo() {
return;
}
</script>
<script>
foo();
</script>
ここでの私の理解は、グローバル オブジェクト (グローバル実行コンテキストで変数オブジェクトとして機能する) は常に存在 (および存続) するため、最初の JavaScript プログラムが関数オブジェクトを作成し、その参照を作成し、次に 2 番目の JavaScript プログラムがその参照を使用して関数を呼び出すというものです。したがって、すべての JavaScript プログラム (単一の Web ページ内) は同じグローバル オブジェクトを「使用」し、1 つの JavaScript プログラムによってグローバル オブジェクトに加えられたすべての変更は、その後に実行されるすべての JavaScript プログラムによって監視できます。
さて、これに注意してください...
<script>
// assuming that foo is not defined
foo();
alert(1);
</script>
上記の場合、アラートコール実行されませんなぜなら、「foo()」ステートメントが ReferenceError をスローし (JavaScript プログラム全体が壊れる)、そのため後続のすべてのステートメントが実行されないからです。
しかし、今回の場合は…
<script>
// assuming that foo is not defined
foo();
</script>
<script>
alert(1);
</script>
さて、警報が鳴った処刑される最初の JavaScript プログラムは ReferenceError をスローし (その結果、中断します)、2 番目の JavaScript プログラムは正常に実行されます。もちろん、ブラウザーはエラーを報告します (ただし、エラーが発生した後、後続の JavaScript プログラムを実行しました)。
さて、私の結論は次のとおりです。
- Web ページの HTML コード内のすべての SCRIPT 要素は、個別の JavaScript プログラムを表します。これらのプログラムは、HTML パーサーがそれらを検出するとすぐに実行されます。
- 同じ Web ページ内のすべての JavaScript プログラムは、同じグローバル オブジェクトを「使用」します。そのグローバル オブジェクトは常に存在します (Web ページが取得された瞬間から Web ページが破棄されるまで)。JavaScript プログラムはグローバル オブジェクトを操作でき、1 つの JavaScript プログラムによってグローバル オブジェクトに加えられたすべての変更は、後続のすべての JavaScript プログラムで確認できます。
- 1 つの JavaScript プログラムが (エラーがスローされて) 中断しても、後続の JavaScript プログラムの実行は妨げられません。
この投稿を事実確認し、何か間違っている点があれば教えてください。
また、この投稿で言及されている動作を説明するリソースは見つかりませんでした。ブラウザメーカーがどこかにそのようなリソースを公開しているはずだと推測していますので、ご存知の場合はリンクを提供してください。
ベストアンサー1
関数の巻き上げ (関数の残りの部分より前にステートメントを評価するプロセスfunction
) は、ECMAScript 標準の一部だと思います (現在参照先が見つかりませんが、EMCAScript に関する議論でこれについて言及しているのを見たことがあります)。script
タグの評価は HTML 標準の一部です。タグが「別のプログラム」であるとは明確には規定されていませんが、スクリプト要素はドキュメントに出現する順序で評価されるとは規定されています。これが、後のスクリプト タグの関数が巻き上げられない理由です。スクリプトはまだ評価されていません。これは、1 つのスクリプトが停止しても後続のスクリプトが切断されない理由でもあります。現在のスクリプトの評価が停止すると、次のスクリプトが開始されます。