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

淺析前端JS腳本放在head與body對(duì)加載的影響以及優(yōu)化策略

 更新時(shí)間:2025年12月03日 08:19:32   作者:拉不動(dòng)的豬  
JS放在不同位置確實(shí)有重要區(qū)別,這涉及到頁面加載性能、用戶體驗(yàn)和代碼執(zhí)行時(shí)機(jī)等多個(gè)方面,下面我們就來看看JS腳本放在head與body是如何影響加載的以及優(yōu)化策略

JS放在不同位置確實(shí)有重要區(qū)別!這涉及到頁面加載性能、用戶體驗(yàn)和代碼執(zhí)行時(shí)機(jī)等多個(gè)方面。

1. 基礎(chǔ)區(qū)別

放在<head>中

<!DOCTYPE html>
<html>
<head>
    <title>頁面標(biāo)題</title>
    <!-- JS在head中 -->
    <script src="script.js"></script>
    <script>
        console.log('head中的腳本執(zhí)行');
        // 此時(shí)DOM還沒有構(gòu)建完成
        document.querySelector('#myButton'); // 可能返回null
    </script>
</head>
<body>
    <div id="content">頁面內(nèi)容</div>
    <button id="myButton">點(diǎn)擊按鈕</button>
</body>
</html>

特點(diǎn):

  • 腳本會(huì)阻塞HTML解析
  • DOM元素還未創(chuàng)建,無法直接操作
  • 會(huì)延遲頁面渲染

放在<body>底部

<!DOCTYPE html>
<html>
<head>
    <title>頁面標(biāo)題</title>
</head>
<body>
    <div id="content">頁面內(nèi)容</div>
    <button id="myButton">點(diǎn)擊按鈕</button>
    
    <!-- JS在body底部 -->
    <script src="script.js"></script>
    <script>
        console.log('body底部的腳本執(zhí)行');
        // 此時(shí)DOM已經(jīng)構(gòu)建完成
        document.querySelector('#myButton'); // 可以正常獲取元素
    </script>
</body>
</html>

特點(diǎn):

  • DOM元素已經(jīng)創(chuàng)建完成,可以直接操作
  • 不會(huì)阻塞頁面首次渲染
  • 用戶能更快看到頁面內(nèi)容

2. 頁面加載過程詳解

瀏覽器解析流程

// 模擬瀏覽器解析過程
console.log('1. 開始解析HTML');

// 遇到head中的script
console.log('2. 暫停HTML解析');
console.log('3. 下載并執(zhí)行JS文件');
console.log('4. JS執(zhí)行完成,繼續(xù)解析HTML');

// 解析body內(nèi)容
console.log('5. 構(gòu)建DOM元素');
console.log('6. 遇到body底部的script');
console.log('7. 執(zhí)行body底部的JS');
console.log('8. 頁面解析完成');

實(shí)際測試示例

<!DOCTYPE html>
<html>
<head>
    <script>
        console.time('head-script');
        console.log('Head腳本開始執(zhí)行');
        
        // 嘗試獲取DOM元素
        const button1 = document.getElementById('test-button');
        console.log('Head中獲取按鈕:', button1); // null
        
        // 模擬一些計(jì)算任務(wù)
        let sum = 0;
        for(let i = 0; i < 1000000; i++) {
            sum += i;
        }
        
        console.log('Head腳本執(zhí)行完成');
        console.timeEnd('head-script');
    </script>
</head>
<body>
    <h1>頁面標(biāo)題</h1>
    <p>這是頁面內(nèi)容</p>
    <button id="test-button">測試按鈕</button>
    
    <script>
        console.time('body-script');
        console.log('Body腳本開始執(zhí)行');
        
        // 嘗試獲取DOM元素
        const button2 = document.getElementById('test-button');
        console.log('Body中獲取按鈕:', button2); // HTMLButtonElement
        
        console.log('Body腳本執(zhí)行完成');
        console.timeEnd('body-script');
    </script>
</body>
</html>

3. 性能影響對(duì)比

Head中的JS - 阻塞渲染

// head中的大型腳本會(huì)阻塞頁面渲染
// script.js (放在head中)
console.log('開始執(zhí)行大型腳本...');

// 模擬復(fù)雜計(jì)算
function heavyComputation() {
    let result = 0;
    for(let i = 0; i < 10000000; i++) {
        result += Math.random();
    }
    return result;
}

const result = heavyComputation();
console.log('計(jì)算完成:', result);

// 在這個(gè)腳本執(zhí)行期間,頁面完全是白屏狀態(tài)
// 用戶看不到任何內(nèi)容

Body底部的JS - 非阻塞渲染

// body底部的相同腳本
// 用戶已經(jīng)能看到頁面內(nèi)容,然后才執(zhí)行這個(gè)腳本
console.log('頁面內(nèi)容已經(jīng)可見,現(xiàn)在執(zhí)行腳本...');

function heavyComputation() {
    let result = 0;
    for(let i = 0; i < 10000000; i++) {
        result += Math.random();
    }
    return result;
}

const result = heavyComputation();
console.log('計(jì)算完成:', result);

4. 現(xiàn)代解決方案 - 腳本屬性

async 屬性

<head>
    <!-- async: 異步下載,下載完立即執(zhí)行 -->
    <script src="analytics.js" async></script>
    <script src="ads.js" async></script>
</head>
<body>
    <div>頁面內(nèi)容</div>
</body>
// async腳本的執(zhí)行時(shí)機(jī)不確定
// analytics.js
console.log('Analytics腳本執(zhí)行'); // 可能在DOM準(zhǔn)備好之前或之后執(zhí)行

// ads.js  
console.log('廣告腳本執(zhí)行'); // 執(zhí)行順序無法保證

defer 屬性

<head>
    <!-- defer: 延遲執(zhí)行,等DOM構(gòu)建完成后按順序執(zhí)行 -->
    <script src="jquery.js" defer></script>
    <script src="main.js" defer></script>
</head>
<body>
    <div>頁面內(nèi)容</div>
</body>
// defer腳本會(huì)按順序執(zhí)行,且在DOM準(zhǔn)備好之后
// jquery.js
window.$ = function() { /* jQuery實(shí)現(xiàn) */ };
console.log('jQuery加載完成');

// main.js (會(huì)在jquery.js之后執(zhí)行)
$(document).ready(function() {
    console.log('DOM準(zhǔn)備完成,jQuery可用');
});

5. 實(shí)際應(yīng)用場景

必須放在Head中的情況

<head>
    <!-- 1. 頁面配置腳本 -->
    <script>
        // 全局配置,需要在頁面渲染前設(shè)置
        window.APP_CONFIG = {
            apiUrl: 'https://api.example.com',
            theme: 'dark'
        };
    </script>
    
    <!-- 2. 字體加載優(yōu)化 -->
    <script>
        // 字體預(yù)加載,避免FOUT (Flash of Unstyled Text)
        if ('fonts' in document) {
            document.fonts.load('1em Arial');
        }
    </script>
    
    <!-- 3. 關(guān)鍵CSS內(nèi)聯(lián) -->
    <script>
        // 根據(jù)條件動(dòng)態(tài)插入關(guān)鍵CSS
        const criticalCSS = `
            body { font-family: Arial; }
            .hero { background: #333; }
        `;
        const style = document.createElement('style');
        style.textContent = criticalCSS;
        document.head.appendChild(style);
    </script>
    
    <!-- 4. 用戶代理檢測 -->
    <script>
        // 需要在頁面渲染前確定設(shè)備類型
        window.isMobile = /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
        if (window.isMobile) {
            document.documentElement.classList.add('mobile');
        }
    </script>
</head>

應(yīng)該放在Body底部的情況

<body>
    <header>
        <h1>網(wǎng)站標(biāo)題</h1>
        <nav id="navigation"><!-- 導(dǎo)航內(nèi)容 --></nav>
    </header>
    
    <main>
        <article id="content"><!-- 主要內(nèi)容 --></article>
        <aside id="sidebar"><!-- 側(cè)邊欄 --></aside>
    </main>
    
    <footer>
        <p>版權(quán)信息</p>
    </footer>
    
    <!-- 這些腳本放在底部 -->
    <script>
        // 1. DOM操作腳本
        const navigation = document.getElementById('navigation');
        navigation.addEventListener('click', function(e) {
            // 處理導(dǎo)航點(diǎn)擊
        });
        
        // 2. 第三方分析腳本
        (function() {
            const ga = document.createElement('script');
            ga.async = true;
            ga.src = 'https://www.google-analytics.com/analytics.js';
            document.head.appendChild(ga);
        })();
        
        // 3. 非關(guān)鍵功能
        function initImageLazyLoading() {
            const images = document.querySelectorAll('img[data-src]');
            // 懶加載邏輯
        }
        
        initImageLazyLoading();
        
        // 4. 社交媒體插件
        if (typeof window.FB === 'undefined') {
            const fb = document.createElement('script');
            fb.src = 'https://connect.facebook.net/en_US/sdk.js';
            document.body.appendChild(fb);
        }
    </script>
</body>

6. 性能優(yōu)化策略

智能加載策略

// 創(chuàng)建動(dòng)態(tài)腳本加載器
class ScriptLoader {
    constructor() {
        this.loadedScripts = new Set();
        this.loadingScripts = new Map();
    }
    
    async loadScript(src, options = {}) {
        if (this.loadedScripts.has(src)) {
            return Promise.resolve();
        }
        
        if (this.loadingScripts.has(src)) {
            return this.loadingScripts.get(src);
        }
        
        const promise = new Promise((resolve, reject) => {
            const script = document.createElement('script');
            script.src = src;
            script.async = options.async !== false;
            script.defer = options.defer || false;
            
            script.onload = () => {
                this.loadedScripts.add(src);
                this.loadingScripts.delete(src);
                resolve();
            };
            
            script.onerror = () => {
                this.loadingScripts.delete(src);
                reject(new Error(`Failed to load script: ${src}`));
            };
            
            // 決定插入位置
            const target = options.target === 'head' ? 
                document.head : document.body;
            target.appendChild(script);
        });
        
        this.loadingScripts.set(src, promise);
        return promise;
    }
    
    // 批量加載腳本
    async loadScripts(scripts) {
        const promises = scripts.map(script => 
            typeof script === 'string' ? 
                this.loadScript(script) : 
                this.loadScript(script.src, script.options)
        );
        
        return Promise.all(promises);
    }
}

// 使用示例
const loader = new ScriptLoader();

// 頁面加載完成后再加載非關(guān)鍵腳本
document.addEventListener('DOMContentLoaded', async () => {
    try {
        // 并行加載多個(gè)腳本
        await loader.loadScripts([
            'https://cdn.jsdelivr.net/npm/chart.js',
            { src: 'analytics.js', options: { defer: true } },
            'social-widgets.js'
        ]);
        
        console.log('所有腳本加載完成');
        initializeFeatures();
    } catch (error) {
        console.error('腳本加載失敗:', error);
    }
});

條件加載

// 根據(jù)頁面類型條件加載腳本
function loadPageSpecificScripts() {
    const currentPage = document.body.dataset.page;
    
    switch (currentPage) {
        case 'product':
            // 產(chǎn)品頁面特定腳本
            loadScript('product-viewer.js');
            loadScript('review-system.js');
            break;
            
        case 'checkout':
            // 結(jié)賬頁面特定腳本
            loadScript('payment-processor.js');
            loadScript('address-validator.js');
            break;
            
        case 'blog':
            // 博客頁面特定腳本
            loadScript('comment-system.js');
            loadScript('social-share.js');
            break;
            
        default:
            // 通用腳本
            loadScript('common-features.js');
    }
}

// 根據(jù)用戶交互加載腳本
function loadOnInteraction() {
    // 用戶首次交互時(shí)加載重型腳本
    function loadHeavyScripts() {
        loadScript('heavy-animation-library.js');
        loadScript('complex-ui-components.js');
        
        // 移除事件監(jiān)聽器,只加載一次
        ['mousedown', 'touchstart', 'keydown'].forEach(event => {
            document.removeEventListener(event, loadHeavyScripts, true);
        });
    }
    
    ['mousedown', 'touchstart', 'keydown'].forEach(event => {
        document.addEventListener(event, loadHeavyScripts, true);
    });
}

// 頁面加載完成后執(zhí)行
document.addEventListener('DOMContentLoaded', () => {
    loadPageSpecificScripts();
    loadOnInteraction();
});

7. 最佳實(shí)踐總結(jié)

現(xiàn)代推薦做法

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>現(xiàn)代網(wǎng)頁</title>
    
    <!-- 1. 關(guān)鍵CSS內(nèi)聯(lián)或預(yù)加載 -->
    <style>/* 關(guān)鍵CSS */</style>
    <link rel="preload" href="main.css" rel="external nofollow"  as="style">
    
    <!-- 2. 重要配置腳本(最小化) -->
    <script>
        window.APP_CONFIG = {/* 基礎(chǔ)配置 */};
    </script>
    
    <!-- 3. 核心庫使用defer -->
    <script src="react.min.js" defer></script>
    <script src="main.js" defer></script>
    
    <!-- 4. 分析腳本使用async -->
    <script src="analytics.js" async></script>
</head>
<body>
    <!-- 頁面內(nèi)容 -->
    <div id="root">
        <h1>頁面內(nèi)容</h1>
        <!-- 其他內(nèi)容 -->
    </div>
    
    <!-- 5. 非關(guān)鍵腳本放在底部或動(dòng)態(tài)加載 -->
    <script>
        // 延遲加載非關(guān)鍵功能
        setTimeout(() => {
            import('./non-critical-features.js');
        }, 1000);
        
        // 基于用戶交互加載
        document.addEventListener('scroll', () => {
            import('./scroll-effects.js');
        }, { once: true });
    </script>
</body>
</html>

使用搭配

位置適用場景優(yōu)點(diǎn)缺點(diǎn)
Head關(guān)鍵配置、用戶代理檢測執(zhí)行早、配置及時(shí)生效阻塞渲染、延遲首屏
Head + defer核心功能庫、框架按順序執(zhí)行、DOM可用需要瀏覽器支持
Head + async獨(dú)立分析腳本、廣告不阻塞解析、并行下載執(zhí)行時(shí)機(jī)不確定
Body底部DOM操作、事件綁定不阻塞渲染、DOM可用可能延遲功能可用時(shí)間
動(dòng)態(tài)加載非關(guān)鍵功能、條件功能最優(yōu)性能、按需加載實(shí)現(xiàn)復(fù)雜、可能影響SEO

到此這篇關(guān)于淺析前端JS腳本放在head與body對(duì)加載的影響以及優(yōu)化策略的文章就介紹到這了,更多相關(guān)JS腳本位置影響內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 淺談js中調(diào)用函數(shù)時(shí)加不加括號(hào)的問題

    淺談js中調(diào)用函數(shù)時(shí)加不加括號(hào)的問題

    下面小編就為大家?guī)硪黄獪\談js中調(diào)用函數(shù)時(shí)加不加括號(hào)的問題 。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-07-07
  • JS模擬實(shí)現(xiàn)哈希表及應(yīng)用詳解

    JS模擬實(shí)現(xiàn)哈希表及應(yīng)用詳解

    這篇文章主要介紹了JS模擬實(shí)現(xiàn)哈希表及應(yīng)用,結(jié)合實(shí)例形式分析了javascript模擬實(shí)現(xiàn)哈希表的步驟、相關(guān)操作技巧與使用方法,需要的朋友可以參考下
    2018-05-05
  • Javascript的字符串方法詳解

    Javascript的字符串方法詳解

    這篇文章主要介紹了Javascript字符串方法詳解的相關(guān)資料,在平時(shí)工作中經(jīng)常會(huì)用到的,非常不錯(cuò),需要的朋友可以參考下,希望能夠給你帶來幫助
    2021-09-09
  • 簡單實(shí)現(xiàn)輪播圖效果的實(shí)例

    簡單實(shí)現(xiàn)輪播圖效果的實(shí)例

    下面小編就為大家?guī)硪黄唵螌?shí)現(xiàn)輪播圖效果的實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-07-07
  • 鼠標(biāo)滾軸控制文本框值的JS代碼

    鼠標(biāo)滾軸控制文本框值的JS代碼

    這篇文章主要介紹了鼠標(biāo)滾軸控制文本框值的JS代碼,有需要的朋友可以參考一下
    2013-11-11
  • TS中最常見的聲明合并(接口合并)

    TS中最常見的聲明合并(接口合并)

    這篇文章主要介紹了TS中最常見的聲明合并:接口合并,TS中的聲明合并,指的就是編譯器會(huì)針對(duì)同名的聲明合并為一個(gè)聲明,合并后的聲明會(huì)同時(shí)擁有原先兩個(gè)或多個(gè)聲明的特性,接口的合并也是一樣,它會(huì)將雙方的成員放到一個(gè)同名的接口里,更多詳細(xì)內(nèi)容請(qǐng)參考下面文章內(nèi)容

    2021-12-12
  • 前端首屏加載速度性能優(yōu)化的實(shí)戰(zhàn)指南

    前端首屏加載速度性能優(yōu)化的實(shí)戰(zhàn)指南

    首屏加載速度是衡量網(wǎng)站用戶體驗(yàn)的關(guān)鍵指標(biāo),本文將分享幾個(gè)在實(shí)際項(xiàng)目中總結(jié)的性能優(yōu)化方案,幫助你的網(wǎng)站首屏加載速度提升80%,大家可以根據(jù)需要進(jìn)行選擇
    2025-11-11
  • javascript中RegExp保留小數(shù)點(diǎn)后幾位數(shù)的方法分享

    javascript中RegExp保留小數(shù)點(diǎn)后幾位數(shù)的方法分享

    文章介紹一篇關(guān)于javascript中RegExp保留小數(shù)點(diǎn)后幾位數(shù)方法,有需要了解的朋友可以參考一下
    2013-08-08
  • 微信小程序基于canvas漸變實(shí)現(xiàn)的彩虹效果示例

    微信小程序基于canvas漸變實(shí)現(xiàn)的彩虹效果示例

    這篇文章主要介紹了微信小程序基于canvas漸變實(shí)現(xiàn)的彩虹效果,結(jié)合實(shí)例形式分析了微信小程序線性漸變及圓形漸變的相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2019-05-05
  • 利用paper.js實(shí)現(xiàn)圖片簡單框選標(biāo)注功能

    利用paper.js實(shí)現(xiàn)圖片簡單框選標(biāo)注功能

    Paper.js是一個(gè) JavaScript庫用來制作繪圖和動(dòng)畫,這篇文章主要介紹了利用paper.js實(shí)現(xiàn)圖片簡單框選標(biāo)注功能的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-10-10

最新評(píng)論

古交市| 康平县| 西峡县| 岳西县| 莲花县| 文安县| 广宗县| 长阳| 象州县| 九龙县| 青冈县| 太保市| 阳原县| 湘潭县| 阜阳市| 桦南县| 连云港市| 平顶山市| 高青县| 美姑县| 离岛区| 紫阳县| 平阴县| 平舆县| 香港 | 无锡市| 石台县| 南雄市| 通渭县| 南充市| 乡城县| 泰兴市| 慈溪市| 沙雅县| 界首市| 兴海县| 通渭县| 民乐县| 建始县| 花莲市| 武平县|