【问题标题】:How many JavaScript programs are executed for a single web-page in the browser?浏览器中的单个网页执行多少个 JavaScript 程序?
【发布时间】:2010-09-17 12:46:24
【问题描述】:

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

  1. 扫描代码以查找函数声明,以及每个 func。声明被“执行”(通过创建函数对象)并创建对该函数的命名引用(以便可以从语句中调用该函数)

  2. 语句按顺序执行(评估)(如它们在代码中出现的那样)

正因为如此,这工作得很好

<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 程序“使用”同一个全局对象。该全局对象始终存在(从获取网页的那一刻起直到网页被销毁)。 JavaScript 程序可以操作 Global 对象,一个 JavaScript 程序对 Global 对象所做的所有更改都可以在所有后续 JavaScript 程序中观察到。
  • 如果一个 JavaScript 程序中断(通过引发错误),这不会阻止后续 JavaScript 程序执行。

请对这篇文章进行事实核查,如果我有什么问题,请告诉我。

另外,我还没有找到解释这篇文章中提到的行为的资源,我认为浏览器制造商一定在某个地方发布了这些资源,所以如果你知道它们,请提供它们的链接。

【问题讨论】:

  • 我从您的问题中删除了答案部分,因为它不属于那里。请随时将其发布为正确的答案。

标签: javascript browser hoisting


【解决方案1】:

函数提升——在函数的其余部分之前评估 function 语句的过程——是 ECMAScript 标准 IIRC 的一部分(我现在找不到参考资料,但我记得看到提到它的 EMCAScript 讨论) . script 标签的评估是 HTML 标准的一部分。它并没有用很多词来说明它们是“单独的程序”,但它确实说脚本元素按照它们在文档中出现的顺序进行评估。这就是后来脚本标签中的函数没有被提升的原因:脚本还没有被评估。这也解释了为什么一个脚本停止并不会切断后续脚本:当当前脚本停止评估时,下一个脚本开始。

【讨论】:

【解决方案2】:

Dmitry Soshnikov 已回答您的问题。正如 ECMAScript 规范所定义的,每个 &lt;script&gt; 元素都作为程序执行。单个页面中的每个程序都使用一个全局对象。就是这样。

【讨论】:

    【解决方案3】:

    它们是独立的程序,但它们修改一个共享的全局对象。

    【讨论】:

      【解决方案4】:

      另一种思考方式是伪本地与全局范围。每个 SCRIPT 声明都有其当前方法/函数的本地范围,以及对当前(先前声明的)全局范围的访问。每当在 SCRIPT 块中定义方法/函数时,它就会被添加到全局范围中,并可供其后的 SCRIPT 块访问。

      另外,这里是来自W3C 的关于脚本声明/处理/修改的进一步参考:

      文档的动态修改 可以建模如下:

      1. 所有 SCRIPT 元素都会在文档加载时按顺序进行评估。
      2. 在给定 SCRIPT 元素中生成的所有脚本结构 SGML CDATA 被评估。他们的 组合生成的文本被插入 代替 SCRIPT 的文件 元素。
      3. 重新评估生成的 CDATA。

      This 是另一个关于脚本/函数评估/声明的好资源。

      【讨论】:

        猜你喜欢
        • 2023-03-12
        • 2013-01-14
        • 2011-04-24
        • 2011-06-18
        • 1970-01-01
        • 2016-06-24
        • 2017-04-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多