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

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

  1. 对代码进行函数声明和每个函数的扫描。 声明是“执行”的(通过创build一个函数对象)并且创build了一个对该函数的命名引用(这样这个函数可以从一个语句中调用)

  2. 语句按顺序执行(评估)(如代码中所示)

因此,这工作得很好

<script> foo(); function foo() { return; } </script> 

虽然“foo”函数在声明之前被调用,但它的工作原理是函数声明在声明之前被计算。

但是,这不起作用

 <script> foo(); </script> <script> function foo() { return; } </script> 

ReferenceError将被抛出(“foo未定义”)。 这导致了这样的结论:网页的HTML代码中的每个SCRIPT元素表示单独的JavaScript程序,并且每当HTML分析器遇到SCRIPT元素时,它就执行该元素内的程序(然后一旦程序被执行,parsing器转到HTML代码后面的SCRIPT元素)。

然后再次,这工作

 <script> function foo() { return; } </script> <script> foo(); </script> 

我的理解是Global对象(作为全局执行上下文中的Variable对象)始终存在(并保留),所以第一个JavaScript程序将创build函数对象并为其创build引用,然后第二个JavaScript程序将使用该引用来调用该函数。 因此,所有JavaScript程序(在单个网页中)“使用​​”相同的全局对象,所有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(并因此中断),但第二个JavaScript程序正常运行。 当然,浏览器会报告错误(尽pipe在错误发生后它执行了后续的JavaScript程序)。

现在我的结论是:

  • 网页的HTML代码中的每个SCRIPT元素代表一个单独的JavaScript程序。 这些程序在HTMLparsing器遇到它们时立即执行。
  • 同一网页中的所有JavaScript程序“使用”相同的全局对象。 该Global对象始终存在(从网页被提取到网页被销毁的那一刻)。 JavaScript程序可能会操纵Global对象,并且所有随后的JavaScript程序都可以观察到一个JavaScript程序对Global对象所做的所有更改。
  • 如果一个JavaScript程序中断(通过抛出错误),这并不妨碍后续JavaScript程序的执行。

请事实检查这个post,并告诉我,如果我有什么问题。

另外,我还没有find解释本文提到的行为的资源,我假设浏览器制造商必须在某处发布这样的资源,所以如果你知道这些资源,请提供链接给他们。

UPDATE!

好吧,我要(尝试)回答我自己的问题:)我从Dmitry答索斯尼科夫(通过电子邮件)(他运行一个关于JavaScript的博客http://www.dmitrysoshnikov.com/ )。

他在这个问题上是这样的:每个SCRIPT块都包含全局代码。 执行每个SCRIPT块会创build一个新的执行上下文。 因此,每个SCRIPT块都有自己的执行上下文,但所有这些执行上下文共享同一个Global对象。

SCRIPT块可以被视为具有相同共享状态的不同“子程序”。

此外,ECMAScript规范(第3版)规定(第10章):“全局代码是被视为ECMAScript程序的源文本”。

德米特里·索什尼科夫回答了你的问题。 每个<script>元素都按照ECMAScript规范的定义执行。 每个程序在一个页面中使用一个全局对象。 而这就是它。

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

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

另一种考虑这个问题的方式是伪本地与全球范围。 每个SCRIPT声明对当前的方法/函数都具有局部范围,并且可以访问当前(以前声明的)全局范围。 无论何时在SCRIPT块中定义一个方法/函数,它都会被添加到全局作用域中,并且可以在SCRIPT块之后被SCRIPT块访问。

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

文档的dynamic修改可以模拟如下:

  1. 所有SCRIPT元素都会在文档加载时进行评估。
  2. 生成SGML CDATA的给定SCRIPT元素中的所有脚本构造都被评估。 它们的组合生成的文本被插入到文档中而不是SCRIPT元素。
  3. 生成的CDATA被重新评估。

这是另一个脚本/function评估/声明的好资源。