有很多不同的方法可以在html页面中包含JavaScript . 我知道以下选项:
-
内联代码或从外部URI加载
-
没有,
defer
或async
属性(仅限外部脚本) -
包含在静态源中或由其他脚本动态添加(在不同的解析状态下,使用不同的方法)
不计算来自硬盘,javascript:URIs和 onEvent
-attributes [3]的浏览器脚本,已经有16个替代方法可以执行JS,我确定我忘了一些东西 .
我对执行顺序更加好奇(这可能取决于加载顺序和document order) . Is there a good (跨浏览器) reference that covers really all cases? 例如http://www.websiteoptimization.com/speed/tweak/defer/仅处理其中的6个,并且主要测试旧浏览器 .
我担心没有,这是我的具体问题:我有一些(外部)头脚本用于初始化和脚本加载 . 然后我在身体的末尾有两个静态的内联脚本 . 第一个允许脚本加载器动态地将另一个脚本元素(引用外部js)附加到正文 . 第二个静态内联脚本想要使用添加的外部脚本中的js . 它可以依赖于已执行的其他(以及为什么:-)?
2 回答
如果您没有动态加载脚本或将它们标记为延迟或异步,则脚本将按照页面中遇到的顺序加载 . 它是外部脚本还是内联脚本无关紧要 - 它们按照页面中遇到的顺序执行 . 外部脚本之后的内联脚本将保留,直到加载并运行之前的所有外部脚本 .
异步脚本(无论它们如何指定为异步)以不可预测的顺序加载和运行 . 浏览器并行加载它们,可以按照自己想要的顺序自由运行它们 .
多个异步事物之间没有可预测的顺序 . 如果需要一个可预测的订单,则必须通过从异步脚本注册加载通知并在加载适当的东西时手动排序javascript调用来编码 .
当动态插入脚本标记时,执行顺序的行为将取决于浏览器 . 您可以在this reference article中查看Firefox的行为方式 . 简而言之,较新版本的Firefox默认动态添加脚本标记为异步,除非已设置脚本标记 .
带有
async
的脚本标记可以在加载后立即运行 . 实际上,浏览器可能会将解析器从其正在执行的任何操作中暂停并运行该脚本 . 所以,它几乎可以随时运行 . 如果脚本被缓存,它可能几乎立即运行 . 如果脚本需要一段时间才能加载,它可能会在解析器完成后运行 .async
要记住的一件事是,它可以随时运行,而且时间不可预测 .带有
defer
的脚本标记将等待整个解析器完成,然后按照遇到的顺序运行标有defer
的所有脚本 . 这允许您将几个彼此依赖的脚本标记为defer
. 它们都将被推迟到文档解析器完成之后,但它们将按照它们遇到的顺序执行,保留它们的依赖关系 . 我认为defer
就像脚本被放入一个队列中,将在解析器完成后处理 . 从技术上讲,浏览器可能在任何时候在后台下载脚本,但是在解析器完成解析页面并解析和运行任何未标记为延迟或异步的内联脚本之后,它们才会执行或阻止解析器 .以下是该文章的引用:
HTML5规范的相关部分(适用于较新的兼容浏览器)是here . 有很多关于异步行为的文章 . 显然,这个规范并没有你可能需要测试来确定的行为 .
来自HTML5规范的引用:
浏览器将按照找到的顺序执行脚本 . 如果调用外部脚本,它将阻止页面,直到加载并执行脚本 .
为了测试这个事实:
动态添加的脚本会在附加到文档后立即执行 .
为了测试这个事实:
警报顺序是“附加” - >“你好!” - >“最后”
如果在脚本中尝试访问尚未到达的元素(例如:
<script>do something with #blah</script><div id="blah"></div>
),则会出现错误 .总的来说,是的,您可以包含外部脚本,然后访问它们的功能和变量,但前提是您退出当前的
<script>
标记并开始新标记 .