在HTML文档中嵌入JavaScript时,在哪里放置<script>标记和包含的JavaScript?我似乎记得,你不应该把这些放在<head>部分,但放在<body>部分的开头也是不好的,因为JavaScript必须在页面完全呈现之前进行解析(或类似的)。这似乎将<body>部分的结尾作为<script>标记的逻辑位置。
那么,哪里是放置<script>标记的正确位置?
(这个问题引用了这个问题,其中建议将JavaScript函数调用从<a>标记移动到<script>标记。我专门使用jQuery,但更一般的答案也是合适的。)
非阻塞脚本标记可以放置在任何位置:
<script src="script.js" async></script>
<script src="script.js" defer></script>
<script src="script.js" async defer></script>
异步脚本一旦可用,将立即异步执行当文档完成解析时执行defer脚本如果不支持异步,异步延迟脚本将返回到延迟行为
这样的脚本将在文档准备就绪后异步执行,这意味着您无法执行此操作:
<script src="jquery.js" async></script>
<script>jQuery(something);</script>
<!--
* might throw "jQuery is not defined" error
* defer will not work either
-->
或者这个:
<script src="document.write(something).js" async></script>
<!--
* might issue "cannot write into document from an asynchronous script" warning
* defer will not work either
-->
或者这个:
<script src="jquery.js" async></script>
<script src="jQuery(something).js" async></script>
<!--
* might throw "jQuery is not defined" error (no guarantee which script runs first)
* defer will work in sane browsers
-->
或者这个:
<script src="document.getElementById(header).js" async></script>
<div id="header"></div>
<!--
* might not locate #header (script could fire before parser looks at the next line)
* defer will work in sane browsers
-->
尽管如此,异步脚本提供了以下优点:
并行下载资源:浏览器可以并行下载样式表、图像和其他脚本,而无需等待脚本下载和执行。源顺序独立性:您可以将脚本放在头部或身体内部,而不必担心阻塞(如果您使用CMS,则很有用)。尽管如此,执行顺序仍然很重要。
使用支持回调的外部脚本可以避免执行顺序问题。许多第三方JavaScript API现在支持非阻塞执行。下面是一个异步加载GoogleMapsAPI的示例。
非阻塞脚本标记可以放置在任何位置:
<script src="script.js" async></script>
<script src="script.js" defer></script>
<script src="script.js" async defer></script>
异步脚本一旦可用,将立即异步执行当文档完成解析时执行defer脚本如果不支持异步,异步延迟脚本将返回到延迟行为
这样的脚本将在文档准备就绪后异步执行,这意味着您无法执行此操作:
<script src="jquery.js" async></script>
<script>jQuery(something);</script>
<!--
* might throw "jQuery is not defined" error
* defer will not work either
-->
或者这个:
<script src="document.write(something).js" async></script>
<!--
* might issue "cannot write into document from an asynchronous script" warning
* defer will not work either
-->
或者这个:
<script src="jquery.js" async></script>
<script src="jQuery(something).js" async></script>
<!--
* might throw "jQuery is not defined" error (no guarantee which script runs first)
* defer will work in sane browsers
-->
或者这个:
<script src="document.getElementById(header).js" async></script>
<div id="header"></div>
<!--
* might not locate #header (script could fire before parser looks at the next line)
* defer will work in sane browsers
-->
尽管如此,异步脚本提供了以下优点:
并行下载资源:浏览器可以并行下载样式表、图像和其他脚本,而无需等待脚本下载和执行。源顺序独立性:您可以将脚本放在头部或身体内部,而不必担心阻塞(如果您使用CMS,则很有用)。尽管如此,执行顺序仍然很重要。
使用支持回调的外部脚本可以避免执行顺序问题。许多第三方JavaScript API现在支持非阻塞执行。下面是一个异步加载GoogleMapsAPI的示例。
放置<script>标记的最佳位置是在关闭</body>标记之前,因此下载和执行它不会阻止浏览器解析文档中的HTML,
此外,从外部加载JavaScript文件也有其自身的优点,比如它将被浏览器缓存,可以加快页面加载时间,它将HTML和JavaScript代码分开,有助于更好地管理代码库。
但现代浏览器还支持其他一些最佳方式,如异步和延迟加载外部JavaScript文件。
异步和延迟
通常HTML页面的执行是逐行开始的。当遇到外部JavaScript<script>元素时,HTML解析将停止,直到下载JavaScript并准备好执行。可以使用defer和async属性更改正常的页面执行。
推迟
当使用defer属性时,JavaScript将与HTML解析并行下载,但只有在完成完整的HTML解析后才能执行。
<script src="/local-js-path/myScript.js" defer></script>
异步
当使用async属性时,一旦遇到脚本,就会立即下载JavaScript,在下载之后,它将与HTML解析一起异步(并行)执行。
<script src="/local-js-path/myScript.js" async></script>
何时使用哪些属性
如果您的脚本独立于其他脚本并且是模块化的,请使用异步。如果使用异步加载script1和script2,则两者都将运行与HTML解析并行,一旦下载并且可用。如果您的脚本依赖于另一个脚本,则对这两个脚本都使用defer:当script1和script2以延迟的顺序加载时,然后,script2将在script1完全执行后执行。如果script2依赖于script1,则必须执行此操作。如果您的脚本足够小并且依赖于另一个脚本然后使用不带属性的脚本,并将其置于所有异步脚本之上。
参考:外部JavaScript JS文件–优点、缺点、语法、属性