我应该将脚本写在HTML的body还是head中?

151

我见过两种方式,都能实现,只是结构有些不同。在你的经验中,哪种更好并且为什么?


请查看非常好的解释和建议:https://dev59.com/NXRC5IYBdhLWcg3wAcbU#24070373 - Grigory Kislin
5个回答

112

实际上,我可以提供多个选项,其中一些在主体中呈现。

  • 将库脚本(如jQuery库)放置在头部。
  • 将普通脚本放在头部,除非出现性能/页面加载问题。
  • 将与包含相关的脚本放置在包含内并在结尾处。其中一个例子是在asp.net页面中的.ascx用户控件-将脚本放在标记末尾。
  • 将影响页面呈现的脚本放在主体的末尾(在主体闭合前)。
  • 不要将脚本放置在标记中,例如<input onclick="myfunction()"/> - 最好将其放在脚本主体内的事件处理程序中。
  • 如果您无法决定,请将其放置在头部,直到有原因不这样做,例如页面阻止问题。

注:最后一项适用于页面阻止(感知加载速度)。用户的感知即是他们的现实-如果它被感知为加载更快,则确实加载更快(即使代码中仍然可能发生某些事情)。

编辑:参考资料:

  • jQuery文档就绪讨论:http://encosia.com/2010/08/18/dont-let-jquerys-document-ready-slow-you-down/?utm_source=feedburner&utm_medium=email&utm_campaign=Feed%3A+Encosia+%28Encosia%29
  • 此问题的其他答案也提供了有效信息。
  • 使用www.google.com和www.bing.com搜索相关信息(有很多参考资料)
  • 注意事项:如果您将脚本块放置在标记中,可能会影响某些浏览器中的布局(IE7和Opera 9.2已知存在此问题),因此请将它们放在隐藏的div中(在div上使用类似于:.hide { display:none; visibility:hidden; }的CSS类)

    标准:请注意,如果有疑问,标准允许将脚本块放置在几乎任何地方:http://www.w3.org/TR/1999/REC-html401-19991224/sgml/dtd.htmlhttp://www.w3.org/TR/xhtml11/xhtml11_dtd.html

    EDIT2:请注意,只要可能(总是?),您应该将实际的Javascript放入外部文件并引用它们-这不会改变相关顺序的有效性。


    2
    你是否有更多关于此页面阻塞问题或浏览器下载资源的信息来源? - Khoi
    到目前为止,这个主题的最佳答案非常有帮助!点赞。 - aIKid
    关于“不要将脚本放置在标记中,例如<input onclick ='myfunction()'/>”,在一些罕见情况下你可能必须这样做。比如在img标签的onerror事件中。 - Andrew
    1
    @Andrew $().on("error", function(){}); 是一个例子,如果您想避免多个错误(在备份图像上),请尝试使用 one 函数 $().one("error", function(){}); - jQuery特定的,但是您可以反转源代码,如果想要纯 JavaScript。 - Mark Schultheiss
    好的提示。我再也不会使用内联的“事件处理程序属性”了 :) - user9016207
    显示剩余3条评论

    43
    在页面头部编写脚本的问题在于阻塞。浏览器必须停止处理页面,直到脚本下载、解析和执行完成。原因很清楚,这些脚本可能向页面中插入更多内容,改变渲染结果,它们还可能删除不需要呈现的内容等。
    一些较新的浏览器违反了此规则,不会在下载脚本时进行阻塞(IE8是第一个这样做的浏览器),但总体来说,下载并不是花费大量时间进行阻塞的主要原因。
    查看《甚至更快的网站》(Even Faster Websites),我刚刚读完了它,它介绍了所有快速将脚本放入页面的方法,包括将脚本放在页面底部以允许渲染完成(提高用户体验)。

    4
    技术上将脚本放在头部是干净的,但从最终用户和SEO的角度来看,将脚本放在文档底部作为最后一项具有许多好处。在一些页面上,只需将脚本移到底部,就可以显著提高页面的响应速度。总体而言,它可能并不会完全更快地加载任何内容,但对于最终用户来说,当他们看到内容时,它感觉更快! - Paul Hadfield
    @Rob 在 HTML 规范中找不到 "blocking" 这个词,它确实提到了渲染的停止(以及脚本插入 HTML 的解释),但并没有明确说明 "blocking",我会进行编辑。 - Ken Struys
    其实我刚才完全理解你的意思。我的意思是,图像文件和声音文件有时无法按时加载或根本无法加载。使用 onload/onready 等事件也没有帮助。我看过一些脚本主要留在 body 中的页面,没有采用任何特殊方法,但仍然能够按时完美地加载页面的所有资源。 - Khoi
    有没有任何基准测试比较在head部分和在关闭body标签部分之前的javascript?这一直感觉像是一个老妇人的故事。浏览器肯定要在解析头部或正文之前下载整个HTML文档吧?为什么现代浏览器会同步处理页面呢?即使遇到某些脚本,也不会停止解析HTML。 - gawpertron
    gawpertron:现代浏览器(从ie8开始)以异步方式进行下载(根据Steve Souders的快速网站)。执行前继续解析的要求源于脚本可以大幅改变DOM的结构。例如,它们可以使用document.write并立即发出文档的部分内容,甚至可能有依赖这些副作用的脚本(请参见此示例,并想象它们是外部脚本http://jsfiddle.net/struys/pZwQw/)。 - Ken Struys
    显示剩余4条评论

    11

    W3Schools有一篇关于这个主题的不错的文章

    <head>中的脚本

    要在调用时执行脚本,或者在触发事件时执行脚本,需要将其放置在函数中。

    将您的函数放在部分中,这样它们都在一个位置,并且不会干扰页面内容。

    <body>中的脚本

    如果您不希望将脚本放置在函数内部,或者如果您的脚本应该编写页面内容,则应将其放置在部分中。


    21
    什么胡说八道... - Vsevolod Golovanov

    4
    标签或在标签关闭之前。 当DOM加载完成后,JS代码会被执行,这正是jQuery的document.ready所做的事情。

    1

    我总是把我的脚本放在头部。原因如下:

    1. 我喜欢将代码和(静态)文本分开
    2. 我通常从外部源加载我的脚本
    3. 同样的脚本被多个页面使用,所以感觉像是一个包含文件(也放在头部)

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接