Skip to content

<script> 标签

<script> 标签用于嵌入或引用 JavaScript 代码。它可以在 HTML 文档中定义客户端脚本,为网页添加交互功能。

概述

<script> 标签用于定义或引用客户端脚本,通常是 JavaScript。它可以嵌入内联脚本或链接到外部脚本文件。

语法

内联脚本

html
<script>
  // JavaScript 代码
</script>

外部脚本

html
<script src="script.js"></script>

常用属性

src 属性

指定外部脚本文件的 URL:

html
<script src="script.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>

type 属性

指定脚本的 MIME 类型(在 HTML5 中可选):

html
<script type="text/javascript">
  // JavaScript 代码
</script>

async 属性

异步执行脚本(不保证执行顺序):

html
<script src="script1.js" async></script>
<script src="script2.js" async></script>

defer 属性

延迟执行脚本(在文档解析完成后执行,保持顺序):

html
<script src="script1.js" defer></script>
<script src="script2.js" defer></script>

crossorigin 属性

设置 CORS 请求的模式:

html
<script src="https://cdn.example.com/script.js" crossorigin="anonymous"></script>

integrity 属性

提供资源的完整性哈希值:

html
<script src="https://cdn.example.com/script.js" 
        integrity="sha384-..." 
        crossorigin="anonymous"></script>

基本用法

内联脚本

html
<!DOCTYPE html>
<html>
<head>
  <title>内联脚本示例</title>
</head>
<body>
  <button id="myButton">点击我</button>
  
  <script>
    document.getElementById('myButton').addEventListener('click', function() {
      alert('按钮被点击了!');
    });
  </script>
</body>
</html>

外部脚本

html
<!DOCTYPE html>
<html>
<head>
  <title>外部脚本示例</title>
</head>
<body>
  <button id="myButton">点击我</button>
  
  <!-- 引用外部脚本文件 -->
  <script src="script.js"></script>
</body>
</html>

对应的 script.js 文件:

javascript
document.getElementById('myButton').addEventListener('click', function() {
  alert('按钮被点击了!');
});

脚本加载策略

默认加载(同步阻塞)

html
<!-- 会阻塞 HTML 解析,直到脚本加载并执行完成 -->
<script src="script.js"></script>

异步加载(async)

html
<!-- 异步加载脚本,不阻塞 HTML 解析 -->
<!-- 不保证脚本执行顺序 -->
<script src="script1.js" async></script>
<script src="script2.js" async></script>

延迟执行(defer)

html
<!-- 延迟执行脚本,在文档解析完成后按顺序执行 -->
<script src="script1.js" defer></script>
<script src="script2.js" defer></script>

位置和执行时机

<head>

html
<!DOCTYPE html>
<html>
<head>
  <title>脚本在头部</title>
  <script src="script.js"></script>
  <script>
    // 这里的代码会立即执行
    console.log('头部脚本执行');
  </script>
</head>
<body>
  <h1>页面内容</h1>
</body>
</html>

<body> 底部(推荐)

html
<!DOCTYPE html>
<html>
<head>
  <title>脚本在底部</title>
</head>
<body>
  <h1>页面内容</h1>
  
  <!-- 在页面内容之后加载脚本 -->
  <script src="script.js"></script>
  <script>
    // DOM 已经加载完成,可以直接操作元素
    console.log('底部脚本执行');
  </script>
</body>
</html>

模块化脚本

ES6 模块

html
<!-- 导入模块 -->
<script type="module" src="main.js"></script>

<!-- 内联模块 -->
<script type="module">
  import { add, multiply } from './math.js';
  
  console.log(add(2, 3)); // 5
  console.log(multiply(2, 3)); // 6
</script>

异步模块

html
<script type="module" async>
  import { fetchData } from './api.js';
  
  const data = await fetchData();
  console.log(data);
</script>

完整示例

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>JavaScript 脚本示例</title>
  
  <!-- 关键库同步加载 -->
  <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
  
  <!-- 模块化脚本 -->
  <script type="module">
    // 导入模块
    import { initializeApp } from './app.js';
    
    // DOM 加载完成后执行
    $(document).ready(function() {
      initializeApp();
    });
  </script>
</head>
<body>
  <header>
    <h1>网页开发教程</h1>
  </header>
  
  <main>
    <section>
      <h2>交互示例</h2>
      <button id="alertButton">显示提示</button>
      <button id="toggleButton">切换内容</button>
      <div id="toggleContent" style="display: none;">
        <p>这是可切换的内容。</p>
      </div>
    </section>
  </main>
  
  <!-- 工具库延迟加载 -->
  <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js" defer></script>
  
  <!-- 页面特定脚本 -->
  <script>
    // 简单的交互功能
    document.getElementById('alertButton').addEventListener('click', function() {
      alert('你好,欢迎学习网页开发!');
    });
    
    document.getElementById('toggleButton').addEventListener('click', function() {
      const content = document.getElementById('toggleContent');
      if (content.style.display === 'none') {
        content.style.display = 'block';
        this.textContent = '隐藏内容';
      } else {
        content.style.display = 'none';
        this.textContent = '显示内容';
      }
    });
    
    // 页面加载完成后的初始化
    document.addEventListener('DOMContentLoaded', function() {
      console.log('页面 DOM 加载完成');
      
      // 发送分析数据
      if (typeof gtag !== 'undefined') {
        gtag('event', 'page_view');
      }
    });
  </script>
  
  <!-- 非关键分析脚本异步加载 -->
  <script src="https://www.google-analytics.com/analytics.js" async></script>
</body>
</html>

错误处理

错误事件监听

html
<script>
  window.addEventListener('error', function(event) {
    console.error('脚本错误:', event.error);
    // 发送错误报告到服务器
  });
</script>

资源加载错误处理

html
<script>
  // 监听脚本加载错误
  document.addEventListener('error', function(event) {
    if (event.target.tagName === 'SCRIPT') {
      console.error('脚本加载失败:', event.target.src);
    }
  }, true);
</script>

安全考虑

内容安全策略 (CSP)

html
<!-- 设置内容安全策略 -->
<meta http-equiv="Content-Security-Policy" 
      content="script-src 'self' https://apis.google.com; object-src 'none'">

子资源完整性 (SRI)

html
<script src="https://cdn.example.com/script.js"
        integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
        crossorigin="anonymous"></script>

避免内联事件处理器

html
<!-- 不推荐 -->
<button onclick="alert('不推荐')">点击</button>

<!-- 推荐 -->
<button id="myButton">点击</button>
<script>
  document.getElementById('myButton').addEventListener('click', function() {
    alert('推荐');
  });
</script>

最佳实践

  1. 脚本位置:将脚本放在 </body> 标签之前以提高页面加载速度
  2. 使用 defer 或 async:对于外部脚本,根据需要使用 deferasync 属性
  3. 模块化:使用 ES6 模块组织代码
  4. 外部脚本:优先使用外部脚本文件以便缓存和复用
  5. 压缩代码:在生产环境中压缩 JavaScript 代码
  6. 错误处理:添加适当的错误处理机制
  7. 安全措施:使用 CSP 和 SRI 提高安全性

浏览器兼容性

<script> 标签在所有浏览器中都得到支持:

  • Chrome
  • Firefox
  • Safari
  • Edge
  • Internet Explorer

不同属性的支持情况:

  • async: IE10+
  • defer: IE10+
  • type="module": 现代浏览器
  • integrity: 现代浏览器

注意事项

  1. <script> 标签可以有结束标签 </script>
  2. 在内联脚本中避免使用 </script> 字符串,可以使用 '<\/script>' 或将其分开放置
  3. 外部脚本和内联脚本不能同时存在于同一个 <script> 标签中
  4. 使用 async 时脚本执行顺序不保证
  5. 使用 defer 时脚本会在 DOM 解析完成后按顺序执行
  6. 模块脚本默认具有 defer 行为

相关标签