<script>标签用于嵌入或引用javascript,实现网页交互与动态功能;2. 内联脚本将代码直接写在标签内,适合小量独有代码,但不利于维护;3. 外部脚本通过src属性引入js文件,提升复用性、可维护性并支持缓存;4. defer使脚本在html解析完成后按顺序执行,不阻塞渲染,适用于依赖dom且有依赖关系的脚本;5. async使脚本下载不阻塞解析,但下载完成后立即执行,不保证顺序,适用于独立第三方脚本;6. 推荐将脚本放在</body>前以避免阻塞页面显示,提升用户体验;7. type="module"支持原生es模块,具备默认defer行为、严格模式和私有作用域,实现模块化开发;8. nomodule与type="module"配合使用,为不支持模块的浏览器提供降级脚本,实现渐进增强。因此,合理使用<script>标签的不同属性和位置策略,能有效优化页面性能与代码结构,完整实现现代前端开发的最佳实践。

在HTML中,<script>标签是用来嵌入或引用客户端脚本(绝大多数情况下是JavaScript)的。它的核心作用就是让你的网页动起来,实现各种交互、数据处理和动态内容展示。你可以用它来直接写一段JS代码,也可以链接到一个外部的JS文件,这在现代网页开发中简直是不可或缺的。

使用<script>标签的基本方式有两种:内联脚本和外部脚本。
1. 内联脚本:
直接将JavaScript代码写在<script>和</script>标签之间。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>内联脚本示例</title>
</head>
<body>
<h1>欢迎来到我的页面</h1>
<button onclick="showAlert()">点我</button>
<script>
// 这是一段内联的JavaScript代码
function showAlert() {
alert('你点击了按钮!');
console.log('按钮被点击了。');
}
</script>
</body>
</html>这种方式适合代码量较小、特定页面独有的脚本。它的优点是请求少,但缺点也很明显:代码复用性差,维护困难,并且混合了HTML和JS,不利于内容与行为分离。
立即学习“前端免费学习笔记(深入)”;
2. 外部脚本:
通过src属性链接到一个外部的JavaScript文件。这是更推荐的做法,特别是对于大型项目或需要复用的脚本。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>外部脚本示例</title>
</head>
<body>
<h1>欢迎来到我的页面</h1>
<button id="myButton">点我</button>
<!-- 引用外部脚本文件 -->
<script src="scripts/main.js"></script>
</body>
</html>对应的scripts/main.js文件内容可能如下:
// scripts/main.js
document.addEventListener('DOMContentLoaded', function() {
const button = document.getElementById('myButton');
if (button) {
button.addEventListener('click', function() {
alert('你点击了外部脚本控制的按钮!');
console.log('外部脚本执行了。');
});
}
});这种方式的好处是显而易见的:代码组织更清晰,易于维护和复用,而且浏览器可以缓存外部JS文件,提高加载速度。
除了src属性,<script>标签还有几个非常重要的属性,它们直接影响脚本的加载和执行行为:
defer: 当你给<script>标签加上defer属性时,脚本会在HTML文档解析完成后才执行,但会在DOMContentLoaded事件触发之前。关键是,它不会阻塞HTML的解析,而且脚本会按照它们在文档中出现的顺序执行。这对于那些依赖DOM但又不想阻塞页面渲染的脚本非常有用。async: 带有async属性的脚本也是异步加载的,不会阻塞HTML解析。但与defer不同的是,async脚本一旦下载完成就会立即执行,不保证执行顺序。这非常适合那些独立于DOM结构、不依赖其他脚本的第三方脚本(比如统计代码)。type: 默认是text/javascript,现在通常可以省略,因为JavaScript是默认的脚本语言。不过,如果你想使用ES模块,就需要设置为type="module"。nomodule: 这个属性通常与type="module"配合使用。如果浏览器支持ES模块(即支持type="module"),它就会忽略带有nomodule属性的脚本。反之,如果浏览器不支持ES模块,它就会执行带有nomodule属性的脚本,这提供了一种优雅的降级方案。脚本标签在HTML文档中的位置,老实说,这不仅仅是编码习惯的问题,它直接关系到你网页的加载性能和用户体验。早些年,大家习惯把所有<script>标签都放在<head>里,觉得这样能让脚本尽早加载。但很快就发现问题了:当浏览器遇到<script>标签时,它会暂停HTML的解析,转而去下载并执行这个脚本。如果脚本文件很大,或者网络状况不佳,整个页面就会在那里“卡”住,用户看到的就是一片空白,直到脚本加载执行完毕。这体验简直是灾难性的。
所以,一个非常普遍且推荐的做法是把<script>标签(特别是那些操作DOM的脚本)放在<body>标签的闭合标签</body>之前。这样做的好处是,浏览器可以先解析并渲染完HTML内容,用户能尽快看到页面的骨架,然后再去加载和执行脚本,这样页面的“感知速度”就大大提升了。用户至少能看到东西,而不是一片白屏。
当然,这种“放到</body>前”的策略也不是万能的。有些时候,脚本确实需要在页面渲染前就执行,比如一些页面级别的配置脚本。这时候,defer和async属性就成了救星。它们允许你在<head>中放置脚本,同时又避免了阻塞渲染,这是一种更现代、更灵活的解决方案。在我看来,理解这些细微的差异,并根据脚本的实际作用选择合适的位置和属性,是前端性能优化的一个基本功。
defer和async这两个属性,虽然都是为了解决脚本阻塞页面渲染的问题,但它们的工作机制和适用场景其实大相径庭。简单来说,它们都让脚本的下载变得非阻塞,但执行时机和顺序却完全不同。
defer:你可以把defer想象成一个“推迟执行”的开关。当浏览器看到带有defer属性的脚本时,它会立即开始下载这个脚本,但不会暂停HTML的解析。脚本的执行会被推迟到HTML文档解析完毕之后,但在DOMContentLoaded事件触发之前。更重要的是,如果页面上有多个带有defer的脚本,它们会按照在HTML中出现的顺序依次执行。这就像排队一样,先到先服务。这对于那些需要操作DOM,并且脚本之间存在依赖关系的场景非常理想。比如,你有一个主脚本依赖于一个库脚本,如果它们都带有defer,那么库脚本会先执行,然后才是你的主脚本。
<head>
<script defer src="lib.js"></script>
<script defer src="main.js"></script>
</head>在这个例子中,lib.js会保证在main.js之前执行。
async:而async则更像是一个“自由奔放”的模式。同样,浏览器会异步下载带有async属性的脚本,不会阻塞HTML解析。但与defer不同的是,一旦脚本下载完成,它就会立即执行,不等待HTML解析完成,也不保证多个async脚本的执行顺序。哪个脚本先下载完,哪个就先执行。这就像一场赛跑,谁先冲过终点线谁就赢。这种行为非常适合那些独立性强、不依赖DOM也不被其他脚本依赖的脚本,比如第三方统计代码、广告脚本等。它们不关心执行顺序,只希望尽快加载并运行。
<head>
<script async src="analytics.js"></script>
<script async src="ads.js"></script>
</head>在这里,analytics.js和ads.js哪个先执行是无法确定的,取决于它们的下载速度。
在我看来,选择defer还是async,关键在于你的脚本是否有序依赖,以及是否需要操作完整的DOM。如果脚本之间有依赖,或者需要等待DOM结构就绪,defer通常是更好的选择。如果脚本是完全独立的,并且越快执行越好,那么async就能提供最大的性能优势。理解这一点,能帮助你做出更明智的性能优化决策。
虽然我们日常开发中几乎都用<script>标签来承载JavaScript代码,但从技术上讲,它并不局限于此。type属性就是用来指定脚本内容的MIME类型。理论上,你可以指定任何脚本语言,比如早期的VBScript,或者更小众的语言,但实际上,浏览器对这些类型的支持非常有限,或者说,现在几乎只有JavaScript一种通用且被广泛支持的客户端脚本语言。所以,type="text/javascript"现在通常可以省略,因为它是默认值。
然而,type属性在现代前端开发中又重新焕发了生机,那就是通过type="module"来引入ES模块(ECMAScript Modules)。这绝对是JavaScript发展史上的一个里程碑,它为前端带来了原生的模块化能力,告别了过去依赖CommonJS或AMD等模块规范的时代。
当一个<script>标签被设置为type="module"时:
import和export语句来组织和共享代码,就像你在Node.js或使用Webpack等打包工具时那样。defer行为:带有type="module"的脚本默认就具备了defer的特性,即异步加载且不阻塞HTML解析,并在DOM解析完成后按顺序执行。你不需要再显式地添加defer属性。export导出的内容才能被其他模块import。<script type="module" src="modules/app.js"></script>
对应的modules/app.js可能长这样:
// modules/utils.js
export function greet(name) {
return `Hello, ${name}!`;
}
// modules/app.js
import { greet } from './utils.js'; // 导入模块
document.addEventListener('DOMContentLoaded', () => {
const message = greet('World');
console.log(message);
document.body.innerHTML += `<h1>${message}</h1>`;
});与type="module"搭配使用的还有nomodule属性。如果你的用户群体中还有一些老旧浏览器不支持ES模块,你可以提供一个带有nomodule属性的脚本作为回退方案。
<script type="module" src="modern-app.js"></script> <script nomodule src="legacy-app.js"></script>
支持ES模块的浏览器会加载并执行modern-app.js,同时忽略legacy-app.js。而那些不支持ES模块的浏览器则会忽略modern-app.js,转而加载并执行legacy-app.js。这种方式提供了一种非常优雅的渐进增强策略。
在我看来,type="module"是前端工程化发展的一个重要标志,它让浏览器原生支持了模块化,极大地简化了前端项目的结构和依赖管理。虽然在实际项目中,我们可能依然会使用Webpack、Vite等打包工具来处理模块、优化代码,但理解原生ES模块的工作原理,无疑是理解现代前端开发基石的关键。
以上就是HTML中的脚本标签怎么用? script标签使用详解的详细内容,更多请关注php中文网其它相关文章!
HTML怎么学习?HTML怎么入门?HTML在哪学?HTML怎么学才快?不用担心,这里为大家提供了HTML速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号