【问题标题】:Is it wrong to place the <script> tag after the </body> tag?把 <script> 标签放在 </body> 标签后面有错吗?
【发布时间】:2011-03-03 12:53:25
【问题描述】:

将脚本标签放在正文的结束标签(&lt;/body&gt;)之后有多大的错误?

<html>
  ....
  <body>
     ....
  </body>
  <script type="text/javascript" src="theJs.js"></script>
</html>

【问题讨论】:

标签: javascript html


【解决方案1】:

它不会在&lt;body&gt; 或&lt;head&gt; 标签之外出现validate。它也不会有太大的区别——除非你在 body 元素完全加载之前进行 DOM 操作,可以在 break IE 之前将它放在关闭 &lt;/body&gt; 之前。

<html>
  ....
  <body>
     ....
     <script type="text/javascript" src="theJs.js"></script>
  </body>
</html>

【讨论】:

  • @epalla:如果你把脚本放在正文标签的末尾,那么到那里时就没有其他内容可以加载了,所以把它放在外面或者只是放在外面应该没有什么区别里面。然后,您的页面仍在验证中的额外好处,这是我试图在我的回答中提出的观点。
  • 是的,我同意你的看法,因为你的回答很好。我只是想补充一点,将 JS 放在页面底部而不是像我们长期以来所做的那样放在头部是有原因的。
  • @PHPst:在某些浏览器中,无效代码可能会产生副作用。无论哪种方式,我都看不出它的缩进比上面的代码小一个制表符宽度如何使它看起来更干净。
  • @PHPst:如果您真的想以这种方式编写代码,我希望浏览器能够应对它。不过,我仍然建议您编写代码进行验证。
  • @technosaurus:总是有&lt;script src="..." defer&gt;,它适用于所有主流浏览器(尽管在 IE9 和更低版本中可能存在重大错误)。
【解决方案2】:

是的。在正文的结束标记之后,只允许使用 cmets 和 html 元素的结束标记。

浏览器可能会执行错误恢复,但你不应该依赖它。

【讨论】:

  • 这是一个更好的答案。当您所要做的只是剪切和粘贴一个结束标记时,有太多新的移动浏览器正在发挥作用。
【解决方案3】:

作为Andy said,文档将无效,但脚本仍将被解释。例如,请参阅 WebKit 中的 the snippet:

void HTMLParser::processCloseTag(Token* t)
{
    // Support for really broken HTML.
    // we never close the body tag, since some stupid web pages close it before
    // the actual end of the doc.
    // let's rely on the end() call to close things.
    if (t->tagName == htmlTag || t->tagName == bodyTag
                              || t->tagName == commentAtom)
        return;
    ...

【讨论】:

  • "支持真正损坏的 html。" -- 我认为它说明了一切。
【解决方案4】:

Internet Explorer 不再允许这样做(我相信是 version 10)并且会忽略此类脚本。

Firefox 和 Chrome 仍然可以容忍它们,但有可能有一天它们会将其作为非标准而放弃。

【讨论】:

  • 然而谷歌在他们的如何做 G+ 登录的例子中这样做了,“最后更新于 2014 年 4 月 10 日”。我从服务器上的 Java 版本 (developers.google.com/+/quickstart/java) 得到它,但大概它是相同的 HTML+js。
【解决方案5】:

在“元素主体”之后按程序插入“元素脚本”是recommended process by W3C 的“解析错误”。在“树构造”中创建一个错误并运行“再次标记化”以处理该内容。所以这就像一个额外的步骤。只有这样它才能运行“脚本执行”——参见the scheme process。

任何其他都是“解析错误”。将“插入模式”切换为“in body”,重新处理token。

从技术上讲,浏览器如何标记和优化它是一个内部过程。

【讨论】:

    【解决方案6】:

    是的。但是如果你在外面添加代码,它很可能不会是世界末日,因为大多数浏览器都会修复它,但这仍然是一个不好的做法。

    【讨论】:

      【解决方案7】:

      从技术上讲,您不应该将脚本标签放在正文标签之后,因为页面内容的呈现以正文结束(或者它是头部?)

      但是浏览器在某种程度上具有容错性(尽管我不会将此作为普遍真理,因为您可能永远不会知道)并且它们会:

      1. 如果脚本标签出现在 body 或 html 标签之外,请将其移回 body 标签中。
      2. 如果脚本标签出现在文档声明之前,则将其移动到头标签中。
      3. 保持原样,如果它出现在文档中的任何其他位置(按源顺序)。

      为了安全起见,您可以:

      1. 将defer 或async 属性与头部中的脚本标记一起使用,或者
      2. 在结束正文标记之前使用脚本标记

      此规范是公认的惯例/惯例,保证消除任何疑虑。

      此外,当您安全并做最 [合理] 的事情时,请记住,您需要 [然后] 担心的是性能,因为内部/外部源文件的加载/下载、解析和解释(s) 取决于 script(s) 标签出现的位置,即使您使用的是 defer 或 async。

      <!-- Moved (prepend) into the head -->
      <script>console.log(1);
      </script>
      <!DOCTYPE html>
      <html lang="en">
      
      <head>
          <meta charset="UTF-8">
          <meta http-equiv="X-UA-Compatible" content="IE=edge">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <!-- Remains where it is -->
          <script>
              console.log(2);
          </script>
          <title>Document</title>
      </head>
      
      <body>
          <h1>Content goes here</h1>
          <!-- Remains where it is -->
          <script>
              console.log(3);
          </script>
          <h1>Content goes here</h1>
      
          <!-- Remains where it is -->
          <script>
              console.log(4);
          </script>
      </body>
      
      </html>
      <!-- Moved (append) into the body -->
      <script>
          console.log(5);
      </script>
      

      【讨论】:

        【解决方案8】:

        Google 实际上在“CSS 优化”方面建议这样做。他们建议内联关键的折叠样式并推迟其余样式(CSS 文件)。

        例子:

        <html>
          <head>
            <style>
              .blue{color:blue;}
            </style>
            </head>
          <body>
            <div class="blue">
              Hello, world!
            </div>
          </body>
        </html>
        <noscript><link rel="stylesheet" href="small.css"></noscript>
        

        见:Optimize CSS Delivery

        【讨论】:

        • 你不应该把东西放在body 元素之外。那篇 Google 文章不建议任何人做任何此类事情。
        • 恐怕谷歌页面说的实际上就是这样。
        • 似乎有一次,那个页面确实推荐了这样的东西,但现在不再推荐了。 (现在有一些使用 javascript 的动态加载。)德文版本不是最新的,仍然包含旧代码示例。
        • "element noscript" 也必须由 RFC 在 "element html" 和 "element body" 中提供
        【解决方案9】:

         <script>
            window.addEventListener('DOMContentLoaded', event => {
        
              // Activate Bootstrap scrollspy on the main nav element
              const sideNav = document.body.querySelector('#sideNav');
              if (sideNav) {
                new bootstrap.ScrollSpy(document.body, {
                  target: '#sideNav',
                  offset: 74,
                });
              };
        
              // Collapse responsive navbar when toggler is visible
              const navbarToggler = document.body.querySelector('.navbar-toggler');
              const responsiveNavItems = [].slice.call(
                document.querySelectorAll('#navbarResponsive .nav-link')
              );
              responsiveNavItems.map(function (responsiveNavItem) {
                responsiveNavItem.addEventListener('click', () => {
                  if (window.getComputedStyle(navbarToggler).display !== 'none') {
                    navbarToggler.click();
                  }
                });
              });
            });
          </script>
          <!-- Bootstrap core JS -->
          <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"></script>

        始终以 body 标记结束,并确保每个 JavaScript 部分都在 body 标记内。您也可以在 head 标记中包含链接或脚本,但不建议这样做,除非您确实确定您的 JavaScript 代码太大而无法内联。

        【讨论】:

          【解决方案10】:

          现代浏览器会像这样在正文中使用脚本标签:

          <body>
              <script src="scripts/main.js"></script>
          </body>
          

          基本上,这意味着脚本将在页面完成后加载,这在某些情况下(即 DOM 操作)可能很有用。但是,我强烈建议您使用相同的脚本并将其放在带有“defer”的头部标签中,因为它会产生相同的效果。

          <head>
              <script src="scripts/main.js" defer></script>
          </head>
          

          【讨论】:

          • 如果script 标签有一个event 属性,可以定义该属性以确定何时解析脚本,这将很有用。所以你有event="load" event="DOMContentLoaded" 用于在创建DOM 后运行脚本或event="beforeunload" 在窗口beforeunload 事件上。例如,&lt;script src="scripts/main.js" event="DOMContentLoaded"&gt;&lt;/script&gt;。
          • 用 defer 放在头部不会有同样的效果;带有 defer, in the head:脚本是异步获取的,只有在 HTML 解析完成后才会执行。而如果您将脚本放在正文的末尾:HTML 解析完成时没有任何暂停,当它完成时,将获取并执行脚本。
          • 如何回答这个问题?问题是“把
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-10-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-01-13
          相关资源
          最近更新 更多