最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

在HTML中引入JavaScript的三種方式及優(yōu)缺點詳解

 更新時間:2026年02月01日 11:48:47   作者:Smilezyl  
本文詳細介紹了HTML中引入JavaScript的三種方式,包括事件句柄的使用(如點擊事件觸發(fā)警告框)、腳本塊的編寫位置及其執(zhí)行順序,以及引入外部JS文件的實踐,需要的朋友可以參考下

核心答案

在 HTML 中引入 JavaScript 有 3 種主要方式

方式語法主要場景
1. 行內(nèi)式<div onclick="alert('hi')">極少使用,不推薦
2. 內(nèi)嵌式<script>alert('hi')</script>小型腳本、單頁應(yīng)用
3. 外鏈?zhǔn)?/strong><script src="app.js"></script>生產(chǎn)環(huán)境首選

核心原則:生產(chǎn)環(huán)境優(yōu)先使用外鏈?zhǔn)剑浜?deferasync 優(yōu)化加載性能。

深入解析

1. 三種方式詳解

方式一:行內(nèi)式(Inline)

<!-- 直接在 HTML 屬性中寫 JS -->
<button onclick="alert('點擊了!')">點擊我</button>
<a href="javascript:void(0)" rel="external nofollow"  onmouseover="console.log('懸停')">鏈接</a>

優(yōu)點:

  • 快速測試、簡單直觀

缺點:

  • ? HTML 和 JS 強耦合,難以維護
  • ? 無法復(fù)用邏輯
  • ? 代碼混亂,可讀性差
  • ? 存在 XSS 安全風(fēng)險
  • ? 無法利用瀏覽器緩存

方式二:內(nèi)嵌式(Internal / Embedded)

<!DOCTYPE html>
<html>
<head>
    <script>
        // JS 代碼寫在 <script> 標(biāo)簽內(nèi)
        function init() {
            console.log('頁面初始化');
        }
    </script>
</head>
<body>
    <h1>內(nèi)嵌式示例</h1>
</body>
</html>

優(yōu)點:

  • ? 適合單頁應(yīng)用或小型項目
  • ? HTML 和 JS 在同一文件,便于調(diào)試
  • ? 可以訪問頁面中的所有元素

缺點:

  • ? HTML 文件體積變大
  • ? 無法被瀏覽器緩存(每次加載 HTML 都要重新加載 JS)
  • ? 多個頁面無法共享同一份 JS 代碼
  • ? 不符合關(guān)注點分離原則

方式三:外鏈?zhǔn)剑‥xternal)?推薦

<!-- 基礎(chǔ)用法 -->
<script src="js/app.js"></script>

<!-- 推薦用法:配合 defer -->
<script src="js/app.js" defer></script>

<!-- 或者 async(取決于場景) -->
<script src="js/analytics.js" async></script>

優(yōu)點:

  • ? HTML 與 JS 分離,結(jié)構(gòu)清晰
  • ? 可復(fù)用:多個頁面共享同一個 JS 文件
  • ? 可緩存:瀏覽器緩存 JS 文件,提升加載速度
  • ? 便于維護:代碼獨立管理
  • ? 支持模塊化:方便團隊協(xié)作

缺點:

  • 需要額外的 HTTP 請求(但可通過緩存和打包優(yōu)化)

2.<script>標(biāo)簽的關(guān)鍵屬性

defer和async的區(qū)別

頁面解析流程對比:

無屬性(默認):
HTML解析 → 遇到script → 停止解析 → 下載JS → 執(zhí)行JS → 繼續(xù)解析HTML
                ↑ 阻塞頁面渲染 ↑

defer:
HTML解析 → 并行下載JS → HTML解析完成 → 按順序執(zhí)行JS → DOMContentLoaded
            ↓ 不阻塞解析 ↓

async:
HTML解析 → 并行下載JS → 下載完立即執(zhí)行 → 繼續(xù)解析HTML
            ↓ 執(zhí)行時機不確定 ↓
屬性執(zhí)行時機順序保證適用場景
無屬性立即執(zhí)行,阻塞解析? 按順序
deferHTML 解析完成后,DOMContentLoaded? 按順序DOM 操作腳本
async下載完成后立即執(zhí)行? 無順序保證獨立腳本(如統(tǒng)計、廣告)
<!-- defer 推薦用法 -->
<script src="main.js" defer></script>
<script src="utils.js" defer></script>
<!-- 保證:utils.js 一定在 main.js 之前執(zhí)行 -->

<!-- async 用法 -->
<script src="analytics.js" async></script>
<script src="ads.js" async></script>
<!-- 不保證執(zhí)行順序,誰先下載完誰先執(zhí)行 -->

其他重要屬性

屬性作用示例
type指定腳本類型type="module"(ES 模塊)
crossoriginCORS 配置crossorigin="anonymous"
integritySRI(子資源完整性校驗)integrity="sha384-..."
nomodule不支持模塊的瀏覽器才執(zhí)行<script nomodule src="legacy.js"></script>

3. 底層機制:瀏覽器如何加載和執(zhí)行腳本

┌─────────────────────────────────────────────────────────┐
│                    瀏覽器渲染流程                         │
├─────────────────────────────────────────────────────────┤
│                                                          │
│  1. HTML Parser ──→ 構(gòu)建 DOM 樹                          │
│         ↓                                                 │
│  2. CSS Parser ──→ 構(gòu)建 CSSOM 樹                         │
│         ↓                                                 │
│  3. 合并 ──→ 渲染樹(Render Tree)                        │
│         ↓                                                 │
│  4. Layout(布局)                                        │
│         ↓                                                 │
│  5. Paint(繪制)                                         │
│                                                          │
└─────────────────────────────────────────────────────────┘

遇到 <script> 時:

默認行為:
┌─────────┐
│ 停止解析 │ ← 阻塞 DOM 構(gòu)建
└────┬────┘
     ↓
┌─────────┐
│ 下載 JS │ ← 如果是外鏈腳本
└────┬────┘
     ↓
┌─────────┐
│ 執(zhí)行 JS │ ← 阻塞渲染
└────┬────┘
     ↓
┌─────────┐
│ 繼續(xù)解析 │
└─────────┘

使用 defer/async:
┌─────────┐      ┌─────────┐
 │繼續(xù)解析 │ ←→   │并行下載 │  ← 不阻塞
└─────────┘      └─────────┘

4. 最佳實踐

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>最佳實踐示例</title>

    <!-- CSS 放在 head 中 -->
    <link rel="stylesheet" href="styles.css" rel="external nofollow" >

    <!-- 預(yù)加載關(guān)鍵腳本 -->
    <link rel="preload" href="critical.js" rel="external nofollow"  rel="external nofollow"  as="script">
</head>
<body>
    <!-- 頁面內(nèi)容 -->

    <!-- 方案1:現(xiàn)代瀏覽器推薦 -->
    <script src="main.js" defer></script>
    <script src="app.js" defer></script>

    <!-- 方案2:需要立即執(zhí)行的腳本(如 polyfill) -->
    <script>
        // 同步執(zhí)行的小型腳本
    </script>

    <!-- 方案3:獨立第三方腳本 -->
    <script src="analytics.js" async></script>

    <!-- 方案4:ES 模塊 -->
    <script type="module" src="module.js"></script>

    <!-- 方案5:模塊降級方案 -->
    <script type="module" src="modern.js"></script>
    <script nomodule src="legacy.js"></script>
</body>
</html>

5. 常見誤區(qū)

? 誤區(qū)1deferasync 功能一樣

? 糾正defer 保證順序且在 DOMContentLoaded 前執(zhí)行,async 不保證順序

? 誤區(qū)2:把所有 <script> 都放在 <head>

? 糾正:傳統(tǒng)放 </body> 前,現(xiàn)代用 defer 可放 head

? 誤區(qū)3defer 的腳本一定在 DOMContentLoaded 前執(zhí)行

? 糾正:大部分情況是的,但如果腳本很大或網(wǎng)絡(luò)慢,可能在之后

? 誤區(qū)4:多個 async 腳本按書寫順序執(zhí)行

? 糾正async 腳本按下載完成順序執(zhí)行,順序不可控

代碼示例

示例1:三種引入方式對比

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>JS 引入方式對比</title>

    <!-- 方式1:行內(nèi)式(不推薦) -->
    <button onclick="handleClick()">行內(nèi)式按鈕</button>

    <!-- 方式2:內(nèi)嵌式 -->
    <script>
        function handleClick() {
            console.log('內(nèi)嵌式函數(shù)被調(diào)用');
        }

        // 內(nèi)嵌式可以直接操作頁面
        document.addEventListener('DOMContentLoaded', function() {
            console.log('DOM 加載完成');
        });
    </script>

    <!-- 方式3:外鏈?zhǔn)剑ㄍ扑]) -->
    <script src="js/utils.js" defer></script>
</head>
<body>
    <h1>三種引入方式</h1>

    <!-- 行內(nèi)式的完整示例 -->
    <div onmouseover="this.style.background='yellow'"
         onmouseout="this.style.background='white'">
        鼠標(biāo)懸停變色
    </div>
</body>
</html>

示例2:defer vs async 實際效果

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>defer vs async</title>
</head>
<body>
    <h1>頁面標(biāo)題</h1>
    <p>內(nèi)容...</p>

    <script>
        // 同步腳本:阻塞后續(xù)渲染
        console.log('1. 同步腳本開始');
        // 模擬耗時操作
        const start = Date.now();
        while (Date.now() - start < 2000) {}
        console.log('2. 同步腳本結(jié)束(阻塞了2秒)');
    </script>

    <p>這行內(nèi)容被延遲顯示了</p>

    <!-- defer 腳本 -->
    <script src="defer1.js" defer></script>
    <script src="defer2.js" defer></script>
    <!-- 保證:defer1.js 在 defer2.js 之前執(zhí)行 -->

    <!-- async 腳本 -->
    <script src="async1.js" async></script>
    <script src="async2.js" async></script>
    <!-- 不保證:誰先下載完誰先執(zhí)行 -->

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            console.log('3. DOMContentLoaded 觸發(fā)');
        });

        window.addEventListener('load', function() {
            console.log('4. 頁面完全加載完成');
        });
    </script>
</body>
</html>

示例3:現(xiàn)代項目的標(biāo)準(zhǔn)引入方式

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>現(xiàn)代項目</title>

    <!-- 預(yù)連接到 CDN -->
    <link rel="preconnect"  rel="external nofollow" >

    <!-- 預(yù)加載關(guān)鍵資源 -->
    <link rel="preload" href="critical.css" rel="external nofollow"  rel="external nofollow"  as="style">
    <link rel="preload" href="critical.js" rel="external nofollow"  rel="external nofollow"  as="script">

    <!-- 關(guān)鍵 CSS -->
    <link rel="stylesheet" href="critical.css" rel="external nofollow"  rel="external nofollow" >

    <!-- Polyfill:需要立即執(zhí)行且不依賴 DOM -->
    <script>
        // 檢測和添加必要的 polyfill
        if (!window.Promise) {
            document.write('<script src="polyfills/promise.js"><\/script>');
        }
    </script>
</head>
<body>
    <div id="app"></div>

    <!-- 主要應(yīng)用腳本:使用 defer -->
    <script src="vendors.js" defer></script>
    <script src="main.js" defer></script>

    <!-- 第三方統(tǒng)計:使用 async -->
    <script src="analytics.js" async></script>

    <!-- ES 模塊 + 降級方案 -->
    <script type="module" src="modern-app.js"></script>
    <script nomodule src="legacy-app.js"></script>
</body>
</html>

示例4:動態(tài)加載腳本

// 動態(tài)創(chuàng)建 script 標(biāo)簽
function loadScript(url, options = {}) {
    return new Promise((resolve, reject) => {
        const script = document.createElement('script');
        script.src = url;

        // 設(shè)置屬性
        if (options.async) script.async = true;
        if (options.defer) script.defer = true;
        if (options.type) script.type = options.type;

        // 事件監(jiān)聽
        script.onload = () => resolve(script);
        script.onerror = () => reject(new Error(`Failed to load ${url}`));

        document.head.appendChild(script);
    });
}

// 使用示例
async function initApp() {
    try {
        await loadScript('/utils.js', { defer: true });
        await loadScript('/main.js', { defer: true });
        console.log('所有腳本加載完成');
    } catch (error) {
        console.error('腳本加載失敗:', error);
    }
}

// 條件加載
if ('IntersectionObserver' in window) {
    // 支持,加載現(xiàn)代版本
    loadScript('/modern-image-lazy-load.js');
} else {
    // 不支持,加載 polyfill
    loadScript('/polyfills/intersection-observer.js')
        .then(() => loadScript('/legacy-image-lazy-load.js'));
}

面試技巧

面試官可能的追問

"為什么傳統(tǒng)建議把 <script> 放在 </body> 之前?"

  • 避免阻塞頁面渲染,讓用戶先看到內(nèi)容

"現(xiàn)在有了 defer,還需要放 </body> 前嗎?"

  • 不需要,defer 可放 head,效果相同且更早開始下載

"什么情況下用 async?"

  • 獨立腳本:統(tǒng)計代碼、廣告腳本、不依賴其他代碼的庫

"多個 defer 腳本的執(zhí)行順序?"

  • 按在 HTML 中的出現(xiàn)順序執(zhí)行

"deferDOMContentLoaded 的關(guān)系?"

  • defer 腳本在 DOMContentLoaded 之前執(zhí)行

"什么是腳本阻塞(render blocking)?"

  • 解釋瀏覽器解析 HTML 時遇到 <script> 停止渲染的機制

如何展示深度理解

談性能優(yōu)化

  • 關(guān)鍵渲染路徑優(yōu)化
  • 資源預(yù)加載(preload/prefetch)
  • 代碼分割(code splitting)

談實際項目經(jīng)驗

  • 如何處理第三方腳本(如 Google Analytics)
  • 如何優(yōu)化首屏加載時間
  • 使用過哪些構(gòu)建工具的優(yōu)化

談瀏覽器兼容性

  • defer/async 的瀏覽器支持情況
  • 如何為老瀏覽器做降級處理

談安全

  • SRI(Subresource Integrity)
  • nonce/CSP(Content Security Policy)

一句話總結(jié)

外鏈?zhǔn)?+ defer 是現(xiàn)代網(wǎng)頁引入 JavaScript 的最佳實踐,它實現(xiàn)了代碼分離、可緩存、不阻塞渲染的完美平衡。

以上就是在HTML中引入JavaScript的三種方式及優(yōu)缺點詳解的詳細內(nèi)容,更多關(guān)于HTML引入JavaScript方式的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論

永年县| 昌吉市| 剑阁县| 济南市| 龙口市| 宜兰县| 通城县| 汾西县| 渝中区| 崇礼县| 屯留县| 诸暨市| 绥宁县| 衡阳市| 台中县| 宜君县| 惠来县| 花莲县| 锡林郭勒盟| 南漳县| 利津县| 宜兰县| 攀枝花市| 赣州市| 阿巴嘎旗| 大邑县| 秦皇岛市| 江口县| 普定县| 庆安县| 马尔康县| 平昌县| 旌德县| 望谟县| 灵石县| 麦盖提县| 县级市| 温泉县| 舞钢市| 宜良县| 定结县|