在浏览器中为单个网页执行了多少个JavaScript程序?

Šim*_*das 67 javascript browser hoisting

JavaScript程序由语句和函数声明组成.执行JavaScript程序时,会执行以下两个步骤:

  1. 扫描代码以查找函数声明和每个函数.声明是"执行"(通过创建一个函数对象),并创建一个对该函数的命名引用(以便可以在语句中调用此函数)

  2. 语句按顺序执行(评估)(因为它们出现在代码中)

因此,这很好用:

<script>
    foo();
    function foo() {
        return;
    }
</script>
Run Code Online (Sandbox Code Playgroud)

虽然"foo"函数在声明之前被调用,但它起作用,因为函数声明在语句之前被计算.

但是,这不起作用:

<script>
    foo();
</script>
<script>
    function foo() {
        return;
    }
</script>
Run Code Online (Sandbox Code Playgroud)

抛出ReferenceError("foo未定义").这导致得出结论,Web页面的HTML代码中的每个SCRIPT元素代表一个单独的JavaScript程序,并且每次HTML解析器遇到SCRIPT元素时,它都会执行该元素内的程序(然后一旦程序执行,解析器转到SCRIPT元素后面的HTML代码.

然后,这确实有效:

<script>
    function foo() {
        return;
    }
</script>
<script>
    foo();
</script>
Run Code Online (Sandbox Code Playgroud)

我的理解是Global对象(在全局执行上下文中充当Variable对象)始终存在(并保持),因此第一个JavaScript程序将创建函数对象并为其创建引用,然后第二个JavaScript程序将使用该引用来调用该函数.因此,所有JavaScript程序(在单个Web页面中)"使用​​"相同的Global对象,并且随后运行的所有JavaScript程序都可以观察到一个JavaScript程序对Global对象所做的所有更改.

现在,请注意这个......

<script>
    // assuming that foo is not defined
    foo();
    alert(1);
</script>
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,警报调用将不会执行,因为"foo()"语句抛出一个ReferenceError(它打破了整个JavaScript程序),因此,所有后续语句都不会执行.

但是,在这种情况下......

<script>
    // assuming that foo is not defined
    foo();
</script>
<script>
    alert(1);
</script>
Run Code Online (Sandbox Code Playgroud)

现在,警报调用确实已执行.第一个JavaScript程序抛出一个ReferenceError(并因此中断),但第二个JavaScript程序正常运行.当然,浏览器会报告错误(尽管它在错误发生后确实执行了后续的JavaScript程序).

现在,我的结论是:

  • Web页面的HTML代码中的每个SCRIPT元素代表一个单独的JavaScript程序.这些程序在HTML解析器遇到它们时立即执行.
  • 同一个网页中的所有JavaScript程序都"使用"相同的Global对象.Global对象始终存在(从提取Web页面到销毁Web页面的那一刻).JavaScript程序可以操作Global对象,并且可以在所有后续JavaScript程序中观察由一个JavaScript程序对Global对象所做的所有更改.
  • 如果一个JavaScript程序中断(通过抛出错误),这不会阻止后续JavaScript程序执行.

请事实查看这篇文章并告诉我是否有错误.

此外,我没有找到解释本文中提到的行为的资源,我认为浏览器制造商必须在某处发布此类资源,因此如果您了解它们,请提供指向它们的链接.

Chu*_*uck 19

函数提升 - 在function函数其余部分之前评估语句的过程- 是ECMAScript标准IIRC的一部分(我现在找不到引用,但我记得看到EMCAScript的讨论提到它).script标签的评估是HTML标准的一部分.它没有指定它们是如此多的单词中的"单独程序",但它确实表示脚本元素按照它们在文档中出现的顺序进行评估.这就是为什么以后的脚本标记中的函数不会被挂起的原因:该脚本尚未被评估.这也解释了为什么一个脚本停止不会切断后续脚本:当前脚本停止评估时,下一个脚本开始.


Tim*_*own 15

Dmitry Soshnikov回答了你的问题.每个<script>元素都作为程序执行,由ECMAScript规范定义.单个页面中的每个程序都使用一个全局对象.这就是它.


Mik*_*tay 7

它们是单独的程序,但它们修改共享的全局对象.