JavaScript 程序由语句和函数声明组成。执行 JavaScript 程序时,会发生以下两个步骤:
扫描代码以查找函数声明和每个函数。声明被“执行”(通过创建函数对象)并创建对该函数的命名引用(以便可以从语句中调用该函数)
语句按顺序执行(评估)(如代码中所示)
正因为如此,这工作得很好:
<script>
foo();
function foo() {
return;
}
</script>
尽管“foo”函数在声明之前被调用,但它之所以有效,是因为函数声明是在语句之前评估的。
但是,这不起作用:
<script>
foo();
</script>
<script>
function foo() {
return;
}
</script>
将抛出 ReferenceError(“未定义 foo”)。这导致了这样的结论:网页的 HTML 代码中的每个 SCRIPT 元素都代表一个单独的 JavaScript 程序,并且每次 HTML 解析器遇到一个 SCRIPT 元素时,它都会执行该元素内的程序(然后一旦程序被执行,解析器转到 SCRIPT 元素后面的 HTML 代码)。
再说一次,这确实有效:
<script>
function foo() {
return;
}
</script>
<script>
foo();
</script>
我在这里的理解是全局对象(作为全局执行上下文中的变量对象)一直存在(并且仍然存在),所以第一个 JavaScript 程序会创建函数对象并为它做一个引用,然后第二个 JavaScript 程序将使用该引用来调用该函数。因此,所有 JavaScript 程序(在单个网页内)“使用”同一个 Global 对象,并且一个 JavaScript 程序对 Global 对象所做的所有更改都可以被随后运行的所有 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(并因此中断),但第二个 JavaScript 程序正常运行。当然,浏览器会报错(虽然它确实执行了后续的 JavaScript 程序,但在发生错误之后)。
现在,我的结论是:
- 网页 HTML 代码中的每个 SCRIPT 元素都代表一个单独的 JavaScript 程序。这些程序在 HTML 解析器遇到它们时立即执行。
- 同一个网页中的所有 JavaScript 程序都“使用”同一个 Global 对象。该 Global 对象始终存在(从获取网页的那一刻起直到网页被销毁)。JavaScript 程序可以操作 Global 对象,一个 JavaScript 程序对 Global 对象所做的所有更改都可以在所有后续 JavaScript 程序中观察到。
- 如果一个 JavaScript 程序中断(通过抛出错误),这不会阻止后续 JavaScript 程序执行。
请事实检查这篇文章,如果我有什么问题,请告诉我。
另外,我还没有找到解释这篇文章中提到的行为的资源,我认为浏览器制造商一定在某个地方发布了这些资源,所以如果你知道它们,请提供它们的链接。