Js执行脚本块的机制

时间:2013-06-27 08:12:33

标签: javascript

我正在学习使用闭包库,Google提醒我们要仔细使用该库:

这不起作用:

<script src="closure-library/closure/goog/base.js"></script>
<script>
  // DON'T DO THIS.
  goog.require('goog.dom');
  var newHeader = goog.dom.createDom('h1');
</script>

我知道原因,因为goog.require会动态添加与goog.dom相关的脚本,并且在goog.dom.xx脚本尚未下载的情况下会立即执行goog.dom,然后它会抛出错误。

但我想知道为什么会这样:

<script src="closure-library/closure/goog/base.js"></script>
<script>
  goog.require('goog.dom');
</script>
<script>
  var newHeader = goog.dom.createDom('h1');
</script>

goog.dom会在goog.require之后立即调用,但为什么它不会抛出错误。

这似乎是由于两段代码驻留在两个script块。

所以我想知道是否有人能解释不同script块和不同位置(头部或身体内部)的JavaScript执行机制?


Romain的回答者更新:

  

解析器看到了这个:

<script src="closure-library/closure/goog/base.js"></script>
<script>
  goog.require('goog.dom');
</script>
<script src="closure-library/closure/goog/dom.js"></script>
<script>
  var newHeader = goog.dom.createDom('h1');
</script>

虽然在<script src="closure-library/closure/goog/dom.js"></script>之前添加了var newHeader = goog.dom.createDom....,但dom.js将被下载,goog.dom.create....完全在dom.js之后执行下载并执行?但我听说js执行是异步的。我错过了什么吗?

1 个答案:

答案 0 :(得分:1)

来自“使用入门”页面:

  

goog.require()调用添加了goog.dom.createDom()的代码   紧接在包含行var newHeader =的脚本标记之前   goog.dom.createDom( 'H1')。

脚本加载器通过将脚本元素插入DOM来加载脚本。它在“当前脚本元素”之后插入。这就是在使用动态加载脚本的函数之前需要“关闭”脚本元素的原因。

如果这是您的源html:

<script src="closure-library/closure/goog/base.js"></script>
<script>
  goog.require('goog.dom');
</script>
<script>
  var newHeader = goog.dom.createDom('h1');
</script>

解析器看到了这个:

<script src="closure-library/closure/goog/base.js"></script>
<script>
  goog.require('goog.dom');
</script>
<script src="closure-library/closure/goog/dom.js"></script>
<script>
  var newHeader = goog.dom.createDom('h1');
</script>

但如果您的来源是:

<script src="closure-library/closure/goog/base.js"></script>
<script>
  goog.require('goog.dom');
  var newHeader = goog.dom.createDom('h1');
</script>

解析器看到了这个:

<script src="closure-library/closure/goog/base.js"></script>
<script>
  goog.require('goog.dom');
  var newHeader = goog.dom.createDom('h1');
</script>
<script src="closure-library/closure/goog/dom.js"></script>

当然不起作用。

脚本执行是同步的。使用脚本元素下载脚本会阻止脚本的执行(以及页面的呈现)。这就是为什么你不应该将不必要的脚本元素放入<head>。这将阻止解析器,从而阻止(a.k.a您的文档)之后的所有内容的呈现,直到下载脚本为止。

在HTML5中,script tags (async)有一个属性,声明浏览器不应等待脚本下载。但默认行为是等待。