JavaScript - head、body或jQuery?

64
这个问题只是为了澄清一些事情。类似这样的问题以前已经被问过了,而这个问题将它们都汇总到了一个问题中 - JavaScript应该放在HTML文档的哪里,或者更重要的是,这是否重要?因此,我要问的其中一件事是,是否…
<head>
<script type="text/javascript">
alert("Hello world!");
</script>
</head>

完全不会有任何功能上的差异
<body>
<!-- Code goes here -->
<script type="text/javascript">
alert("Hello world!");
</script>
</body>

更重要的是,我想专注于修改或使用DOM元素的JS。因此,我知道如果在中的之前放置像document.getElementById("test").innerHTML = "Hello world!"这样的内容,则不起作用,因为body从顶部向下加载,使JS首先加载,然后会尝试操作尚不存在的元素。所以它应该像上面那样放在中或者就在标记之前。问题是,除了组织和排序之外,选择其中一个是否有影响,如果有,影响是什么?
当然,还有第三种方法-使用jQuery:
$(document).ready(function(){ /*Code goes here*/ });

这样做的好处是,无论你在身体的哪个位置放置代码,它都只会在所有内容加载完后执行。问题在于,值得引入一个巨大的JS库仅仅为了使用一个方法吗?这个方法的需要是否可以通过准确放置脚本来替代?我想在这里澄清一些事情,如果你愿意回答的话,请继续!总结:不同类型的脚本应该放在哪里-头还是身体,或者这重要吗?jQuery是否值得仅仅为了ready事件而使用?

1
那么这个问题我应该在<head></head>中还是在</body>附近声明用于我的页面的JavaScript文件?没有为您澄清吗?无论如何,如果您对“ready”功能感兴趣,可以查看源代码并在需要时复制它。 - Felix Kling
4
“jQuery方法”可以使用原生JavaScript实现:window.onload = function(){} --不需要使用任何库。 - Gary
@Felix - 对不起,可能是我漏掉了。另外,既然我在问这个问题,你应该能想到我对JS有点小白,所以我真的无法想象自己试图翻阅jQuery源代码:P - Bluefire
@所有人的回答 - 你们的意思是把脚本放在头部会减慢页面加载速度;这是否意味着如果我有很多JS,我应该将其放在</body>之前,而如果只有几行代码,我可以将其放在头部,因为那不会减慢加载速度太多? - Bluefire
3个回答

61
最推荐的方法是将其放置在</body>标签之前。Yahoo性能文章还建议使用雅虎和谷歌分别提供的YSlowPage Speed插件。

引用上面链接的雅虎文章:

问题在于脚本会阻塞并行下载。HTTP/1.1规范建议浏览器每个主机名同时下载不超过两个组件。如果您从多个主机名提供图像,则可以实现超过两个下载的并行下载。但是,在下载脚本时,浏览器不会启动任何其他下载,即使在不同的主机名上也是如此。当您将脚本放入标签中时,浏览器会获取它们,从而使其他内容保持暂停状态,直到加载脚本,用户会感觉页面加载缓慢。这就是为什么您应该将脚本放在底部的原因。
$(document).ready(function(){/*Code goes here*/});

当DOM可用并且可以被操作时,它会被触发。如果您将代码放在末尾,则不一定需要此操作,但通常需要此操作,因为您希望在DOM可用于使用时立即执行某些操作。


这是一个很好的答案,但如果您需要在包含jquery之前使用类似$("td.speical-format").live()这样的东西,该怎么办? - Dodzi Dzakuma
如果您要将其放在最后,请始终使用旋转器/加载程序。这是因为如果您的CSS / JS很大或数量很大,则某些依赖于jQuery的内容将无法正常工作... - DragonFire
根据您的观点,您说我们应该将JS库文件下载到底部。除非我们使用async,否则它将成为渲染阻塞JavaScript。但是JS库文件应该在绘画过程完成后准备好,以便自定义JavaScript(例如:document.ready())运行其函数,不是吗? - lpradhap

29

虽然常见的做法是将script标签放在head中,但这通常不是一个好主意,因为它会阻止页面的渲染,直到这些脚本已被下载和处理(除非使用asyncdefer以及浏览器支持它们)。

通常推荐的方法是将script标签放在body标签的最后,例如紧随其后的</body>之前。这样,上面所有的DOM元素都将可访问(请参阅下面的链接)。其中的一个注意点是,在您的页面至少部分渲染但尚未处理脚本时,可能会有一个简短的时间窗口,如果用户开始与页面交互,他们可能会执行某些事件,而您的脚本还没有时间挂钩。因此,您需要知道这一点。这就是渐进增强的原因之一,这个想法是页面将可以不依赖JavaScript工作,但使用JavaScript效果更佳。如果您正在设计一个完全不能没有JavaScript的页面/应用程序,您可以在body标签的顶部包含一些内联脚本(例如: <script>minimal code here</script>),它将挂钩任何冒泡事件on document.body并将其排队以在脚本加载时执行,或者只是要求用户等待。

使用像jQuery的ready这样的功能是可以的,但除了在库(例如,如果您控制script标签的位置,则通常不需要使用它;但如果您编写一个需要在加载时执行某些操作的jQuery插件[这相对较少,通常它们只是等待被调用],则通常需要使用它)之外并不是必需的。

更多阅读材料:


所以,如果我正在制作一个需要JS的应用程序,我应该使用内联钩子;那么如果我正在制作一个Chrome扩展程序(其中不允许使用内联JS),该怎么办? - Bluefire
@Bluefire:我并没有说你应该这样做,只是这是一种防御那个短暂间隔的方法之一。你是在说你不能在Chrome扩展中执行<script>code here</script>吗? - T.J. Crowder
不行,我是说你不能这样做 <span oncick="yourEvent()"></span>。我以为这就是你所说的“内联”。 - Bluefire
@Bluefire:啊,抱歉,我的意思是内联,即script元素直接包含其代码,而不是引用单独的脚本文件。 - T.J. Crowder

7

可以通过如下方式并行下载JavaScript:

(function () {
    var ele = document.createElement('script');
    ele.src = "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js";
    ele.id = "JQuery";
    ele.onload = function () {
        //code to be executed when the document has been loaded
    };
    document.getElementsByTagName('head')[0].appendChild(ele);
})();

在这个例子中,它从Google下载压缩过的JQuery v1.7.2,这是一个很好的下载JQuery的方法,因为从Google下载就像使用CDN一样,如果用户曾经访问过使用相同文件的页面,它可能已经被缓存,因此不需要重新下载。
这里有一个非常好的Google技术讲座,关于这个问题,链接在这里:http://www.youtube.com/watch?v=52gL93S3usU&feature=plcp

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