淺談 JavaScript 性能優化

文章目錄

    • 概要
    • 一、代碼執行優化
      • 1. 減少全局變量訪問
      • 2. 避免不必要的計算
      • 3. 優化循環操作
    • 二、內存管理優化
      • 1. 減少內存泄漏
      • 2. 對象池與內存復用
    • 三、渲染性能優化
      • 1. 避免強制同步布局
      • 2. 減少 DOM 操作
      • 3. 優化動畫與合成
    • 四、網絡加載優化
      • 1. 代碼壓縮與 Tree Shaking
      • 2. 按需加載與懶加載
      • 3. 緩存策略
    • 五、其他優化技巧
      • 1. 避免 eval() 和 with 語句
      • 2. 使用高效的數據結構
      • 3. 性能監控與分析
    • 總結
    • 性能優化之vue3
      • 一、響應式系統優化
        • 1. 避免過度響應式
        • 2. 局部響應式替代全局響應式
      • 二、組件設計優化
        • 1. 使用 `v-once` 緩存靜態內容
        • 2. 使用 `v-memo` 緩存重復渲染的列表項
        • 3. 組件懶加載與 Suspense
      • 三、渲染與更新優化
        • 1. 避免不必要的 watch
        • 2. 優化計算屬性
      • 四、事件處理優化
        • 1. 防抖/節流處理高頻事件
        • 2. 避免在循環中綁定復雜事件處理函數
      • 五、內存管理優化
        • 1. 手動清理副作用
        • 2. 避免組件間循環引用
      • 六、構建與部署優化
        • 1. 代碼分割與按需加載
        • 2. 使用生產模式構建
      • 性能優化檢查清單

概要

JavaScript 性能優化是提升網頁加載速度、交互流暢度和用戶體驗的關鍵手段。以下從代碼執行效率、內存管理、渲染優化等方面進行淺談。

一、代碼執行優化

1. 減少全局變量訪問

  • 原因:全局變量在作用域鏈頂端,訪問速度慢于局部變量。
  • 優化
    • 將常用全局變量緩存為局部變量(如 const doc = document)。
    • 使用模塊系統(ES6 Modules)或閉包封裝變量,避免污染全局作用域。

2. 避免不必要的計算

  • 防抖(Debounce)與節流(Throttle)
    • 防抖:事件觸發后延遲執行,若短時間內多次觸發則重新計時(適用于搜索聯想、窗口 resize 等)。
    • 節流:限制事件觸發頻率,確保單位時間內最多執行一次(適用于滾動加載、高頻點擊等)。
  • 示例代碼
    // 防抖
    function debounce(fn, delay) {let timer = null;return function (...args) {clearTimeout(timer);timer = setTimeout(() => fn.apply(this, args), delay);};
    }// 節流(時間戳版)
    function throttle(fn, delay) {let lastTime = 0;return function (...args) {const now = Date.now();if (now - lastTime >= delay) {fn.apply(this, args);lastTime = now;}};
    }
    

3. 優化循環操作

  • 使用高效循環方式
    • 優先使用 for 循環而非 forEach(后者存在函數調用開銷)。
    • 緩存循環長度(如 for (let i = 0, len = arr.length; i < len; i++))。
  • 避免循環內的復雜操作:將耗時邏輯移至循環外。

二、內存管理優化

1. 減少內存泄漏

  • 常見場景
    • 全局變量未及時清理(如意外掛載在 window 上的對象)。
    • 定時器或事件監聽器未移除(如 addEventListener 需搭配 removeEventListener)。
    • DOM 元素與 JavaScript 對象的循環引用(如緩存 DOM 節點時未斷開引用)。
  • 優化方法
    • 使用嚴格模式('use strict')檢測未聲明變量。
    • 手動清理定時器(clearTimeout/clearInterval)和事件監聽器。
    • 使用弱引用(WeakMap/WeakSet)避免對象被意外引用。

2. 對象池與內存復用

  • 對象池模式:預先創建一組可復用的對象,避免頻繁創建/銷毀帶來的開銷(如游戲中的子彈對象)。
  • 示例
    const objectPool = {pool: [],create() {return this.pool.length ? this.pool.pop() : new Object();},recycle(obj) {// 重置對象狀態obj.property = null;this.pool.push(obj);}
    };
    

三、渲染性能優化

1. 避免強制同步布局

  • 原因:瀏覽器渲染流程為“樣式計算 → 布局 → 繪制 → 合成”,強制同步布局(如在修改樣式后立即讀取布局屬性)會觸發額外重排。
  • 優化
    • 批量修改樣式:使用 classList 替代直接操作 style,或通過 documentFragment 批量操作 DOM。
    • 錯誤示例
      element.style.width = '100px'; // 觸發布局
      console.log(element.offsetWidth); // 強制同步布局,導致額外重排
      
    • 正確示例
      element.classList.add('new-style'); // 批量修改
      

2. 減少 DOM 操作

  • 使用文檔碎片(Document Fragment):將多次 DOM 修改合并為一次操作。
    const fragment = document.createDocumentFragment();
    data.forEach(item => {const li = document.createElement('li');li.textContent = item;fragment.appendChild(li);
    });
    ul.appendChild(fragment);
    
  • 避免頻繁操作內聯樣式:優先通過 CSS 類名控制樣式。

3. 優化動畫與合成

  • 使用 requestAnimationFrame:將動畫操作綁定到瀏覽器的刷新周期,避免丟幀。
    let progress = 0;
    function animate() {progress += 1;element.style.transform = `translateX(${progress}px)`;if (progress < 100) requestAnimationFrame(animate);
    }
    requestAnimationFrame(animate);
    
  • 利用 CSS 合成層:對頻繁動畫的元素設置 will-change: transformtransform: translateZ(0),使其單獨成為一個合成層,減少重繪影響。

四、網絡加載優化

1. 代碼壓縮與 Tree Shaking

  • 工具:使用 Webpack、Rollup 等打包工具壓縮代碼,移除未使用的代碼(Tree Shaking,需配合 ES6 模塊)。

2. 按需加載與懶加載

  • 按需加載:通過動態導入(import('./module.js'))實現路由或組件的異步加載。
  • 懶加載:對非關鍵資源(如圖片、非首屏腳本)延遲加載,使用 Intersection Observer 監聽元素進入視口。

3. 緩存策略

  • 使用 localStorage/sessionStorage:緩存頻繁訪問的數據(如用戶配置)。
  • HTTP 緩存:設置 Cache-Control 頭,合理利用瀏覽器緩存靜態資源。

五、其他優化技巧

1. 避免 eval() 和 with 語句

  • 原因eval() 會阻塞 JavaScript 引擎優化,with 會導致作用域鏈變長,影響性能。

2. 使用高效的數據結構

  • 場景
    • 頻繁查找:用 Map 替代對象(鍵可非字符串,且遍歷性能更優)。
    • 有序數據:用 ArraySet(去重場景)。

3. 性能監控與分析

  • 工具
    • 瀏覽器 DevTools(Performance 面板錄制性能分析)。
    • Lighthouse 審計性能指標(如 FCP、LCP、TTI 等)。

總結

性能優化需遵循“過早優化是萬惡之源”原則,優先通過 profiling 定位瓶頸,再針對性優化。核心思路包括:減少計算量、降低內存占用、優化渲染流程、提升資源加載效率。實際項目中可結合框架特性(如 React 的 useMemo/useCallback、Vue 的 v-show/v-if 合理使用)進一步提升性能。

性能優化之vue3

在 Vue3 中,性能優化需結合 Composition API、響應式原理和渲染機制進行針對性處理。以下從代碼結構、響應式優化、渲染效率等角度提供實例和避坑指南:

一、響應式系統優化

1. 避免過度響應式

問題場景:將大型靜態數據(如常量配置、初始表單值)放入響應式對象會增加不必要的依賴追蹤開銷。

優化方案

  • 使用 readonly 包裝靜態數據
  • 使用普通 JS 對象存儲無需響應式的數據
import { ref, readonly } from 'vue'// 錯誤示例:將常量配置轉為響應式
const config = reactive({API_URL: 'https://api.example.com',MAX_FILE_SIZE: 1024
})// 正確示例:使用 readonly 包裝靜態數據
const config = readonly({API_URL: 'https://api.example.com',MAX_FILE_SIZE: 1024
})// 正確示例:表單初始值使用普通對象
const initialFormData = {name: '',age: 0
}
const formData = ref({ ...initialFormData })
2. 局部響應式替代全局響應式

問題場景:在組件中使用 reactive 創建大型對象時,所有屬性都會被遞歸轉為響應式,導致性能開銷。

優化方案

  • 使用 ref 替代 reactive 存儲復雜結構
  • 對無需響應式的深層屬性使用 shallowReactive/shallowRef
import { ref, shallowReactive } from 'vue'// 錯誤示例:遞歸響應式大型對象
const tableData = reactive({list: [], // 可能包含大量數據pagination: { page: 1, size: 10 }
})// 正確示例:僅表層響應式
const tableData = shallowReactive({list: ref([]), // 列表數據變化時手動更新pagination: { page: 1, size: 10 }
})

二、組件設計優化

1. 使用 v-once 緩存靜態內容

適用場景:包含大量靜態內容的組件(如介紹文案、幫助信息)

<template><div><!-- 靜態內容只需渲染一次 --><div v-once class="static-content"><h1>關于我們</h1><p>公司簡介:...(大量靜態文本)</p></div><!-- 動態內容正常渲染 --><div class="dynamic-content"><p>當前時間:{{ currentTime }}</p></div></div>
</template>
2. 使用 v-memo 緩存重復渲染的列表項

適用場景:列表項中大部分數據不變,僅少量字段變化

<template><div><!-- 僅當 item.id 或 item.name 變化時才重新渲染 --><div v-for="item in list" v-memo="[item.id, item.name]" :key="item.id"><span>{{ item.name }}</span><span>{{ expensiveComputation(item) }}</span> <!-- 復雜計算 --></div></div>
</template>
3. 組件懶加載與 Suspense

適用場景:非首屏組件(如模態框、詳情頁)

<template><div><button @click="showDetail = true">查看詳情</button><!-- 按需加載詳情組件 --><Suspense v-if="showDetail"><template #default><LazyDetailComponent :id="itemId" /></template><template #fallback><div>加載中...</div></template></Suspense></div>
</template><script setup>
import { ref } from 'vue'// 懶加載組件
const LazyDetailComponent = defineAsyncComponent(() => import('./DetailComponent.vue'))const showDetail = ref(false)
const itemId = ref(1)
</script>

三、渲染與更新優化

1. 避免不必要的 watch

問題場景:監聽大型對象導致頻繁觸發回調

優化方案

  • 監聽特定屬性而非整個對象
  • 使用 deep: true 時結合 immediate: false 避免初始觸發
import { watch } from 'vue'const formData = ref({name: '',age: 0,address: {city: '',street: ''}
})// 錯誤示例:監聽整個對象
watch(formData, (newVal) => {// 每次任何屬性變化都會觸發
})// 正確示例:監聽特定屬性
watch(() => formData.value.name, (newName) => {// 僅 name 變化時觸發
})// 正確示例:深度監聽(僅在必要時使用)
watch(() => formData.value.address, (newAddress) => { /* ... */ },{ deep: true, immediate: false }
)
2. 優化計算屬性

問題場景:復雜計算屬性未緩存結果,導致重復計算

優化方案

  • 確保計算屬性純函數化
  • 對耗時計算使用緩存策略
import { computed } from 'vue'const list = ref([1, 2, 3, 4, 5])// 錯誤示例:包含副作用的計算屬性
const filteredList = computed(() => {console.log('計算中...') // 每次訪問都會執行return list.value.filter(item => item > 3)
})// 正確示例:純函數計算屬性
const filteredList = computed(() => list.value.filter(item => item > 3))// 復雜計算的緩存優化
const expensiveResult = computed(() => {// 使用 WeakMap 緩存計算結果const cache = new WeakMap()if (cache.has(list.value)) {return cache.get(list.value)}const result = /* 復雜計算邏輯 */cache.set(list.value, result)return result
})

四、事件處理優化

1. 防抖/節流處理高頻事件

適用場景:搜索聯想、滾動加載、窗口大小變化

<template><div><input v-model="searchText" @input="debouncedSearch" /></div>
</template><script setup>
import { ref } from 'vue'
import { debounce } from 'lodash-es' // 或自定義防抖函數const searchText = ref('')// 創建防抖函數
const debouncedSearch = debounce((value) => {fetchData(value) // 執行搜索請求
}, 300)
</script>
2. 避免在循環中綁定復雜事件處理函數

問題場景:大型列表中每個項都綁定復雜事件處理函數

優化方案

  • 使用事件委托
  • 將事件處理函數提取到組件外部
<template><!-- 錯誤示例:每個項都創建新的處理函數 --><ul><li v-for="item in list" :key="item.id" @click="() => handleClick(item)">{{ item.name }}</li></ul><!-- 正確示例:事件委托 --><ul @click="handleListClick"><li v-for="item in list" :key="item.id" :data-id="item.id">{{ item.name }}</li></ul>
</template><script setup>
import { ref } from 'vue'const list = ref([...])// 事件委托處理函數
const handleListClick = (event) => {const targetId = event.target.closest('li').dataset.idif (targetId) {// 處理點擊邏輯}
}
</script>

五、內存管理優化

1. 手動清理副作用

問題場景:定時器、WebSocket、自定義事件未清理導致內存泄漏

優化方案

  • onUnmounted 鉤子中清理副作用
  • 使用 watch 的停止函數
import { onUnmounted, watch } from 'vue'// 定時器示例
let timer = nullconst setupTimer = () => {timer = setInterval(() => {// 定時任務}, 1000)
}// 組件卸載時清理
onUnmounted(() => {clearInterval(timer)
})// watch 停止函數示例
const stop = watch(source, (newVal) => {// 監聽邏輯
})// 手動停止監聽
stop()
2. 避免組件間循環引用

問題場景:父組件引用子組件,子組件又引用父組件

優化方案

  • 通過事件或狀態管理(如 Pinia)解耦組件通信
  • 使用 provide/inject 替代直接引用
// 錯誤示例:父子組件循環引用
// Parent.vue
import Child from './Child.vue'// Child.vue
import Parent from './Parent.vue'// 正確示例:使用事件通信
// Parent.vue
<Child @custom-event="handleEvent" />// Child.vue
const emit = defineEmits(['custom-event'])
emit('custom-event', data)

六、構建與部署優化

1. 代碼分割與按需加載

配置方案:在 Vite/Webpack 中配置動態導入

// router.js
const routes = [{path: '/dashboard',name: 'Dashboard',// 動態導入組件component: () => import('../views/Dashboard.vue')}
]
2. 使用生產模式構建

優化效果

  • 移除開發環境代碼(如 console.logprocess.env.NODE_ENV 判斷)
  • 壓縮混淆代碼
  • 啟用 Tree Shaking
# Vite 構建命令
npm run build -- --mode production

性能優化檢查清單

  1. 響應式檢查

    • 是否將大型靜態數據轉為響應式?
    • 是否使用 shallowReactive 避免深層響應式?
  2. 渲染效率檢查

    • 是否使用 v-once 緩存靜態內容?
    • 是否使用 v-memo 優化列表渲染?
    • 是否有不必要的組件重新渲染?
  3. 內存管理檢查

    • 是否清理了所有定時器和事件監聽器?
    • 是否存在組件間循環引用?
  4. 構建優化檢查

    • 是否按需加載非首屏組件?
    • 是否使用生產模式構建?

通過以上優化手段,可有效提升 Vue3 應用的性能表現。建議結合瀏覽器 DevTools 的 Performance 面板進行性能分析,針對性地解決瓶頸問題。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/83058.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/83058.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/83058.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

mongodb nosql數據庫筆記

MongoDB 簡介 MongoDB 是一個開源的 NoSQL 數據庫&#xff0c;采用文檔存儲模型&#xff08;BSON 格式&#xff0c;類似 JSON&#xff09;&#xff0c;支持高靈活性、水平擴展和高性能的數據操作。與傳統關系型數據庫&#xff08;如 MySQL&#xff09;不同&#xff0c;MongoDB…

Flutter實現不規則瀑布流布局拖拽重排序

因為業務&#xff0c;所以需要用flutter去實現一種不規則圖形的瀑布流&#xff0c;但是同時需要支持拖拽并重新排序。效果類似如下。 查詢過現有的插件&#xff0c;要么是僅支持同樣大小的組件進行排序&#xff0c;要么就是動畫效果不是很滿意&#xff0c;有點死板&#xff0c;…

微信小程序(uniapp)實現騰訊云 IM 消息撤回

uniapp 實現騰訊云 IM 消息撤回功能實戰指南 一、功能實現原理 騰訊云 IM 的消息撤回功能通過 消息修訂&#xff08;Message Revision&#xff09; 機制實現&#xff0c;核心流程如下&#xff1a; 發送方調用撤回 API 刪除指定消息云端生成撤回通知消息&#xff08;類型為 T…

AI入門示例

市面上有很多AI大模型&#xff0c;這里以 智譜的大模型 為示例 1.先要注冊智譜AI開放平臺 2.注冊成功后&#xff0c;會贈送3個月的免費額度&#xff0c;如下 3.然后去控制臺&#xff0c;創建一個API KEY 4.接著就可以開始寫代碼了 提前導入包&#xff1a; openai 示例1&…

【數據結構】單鏈表練習

1.鏈表的中間節點 https://leetcode.cn/problems/middle-of-the-linked-list/description/ 用快慢指針來解決 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ struct ListNode* middleNode(struct ListNode* he…

嘗鮮純血鴻蒙,華為國際版本暫時不支持升級。如mateX6 國際版?為什么不支持?什么時候支持?

一&#xff1a;mateX6 國際版支持鴻蒙嗎&#xff1f; 不支持 二&#xff1a;華為國際版支持鴻蒙嗎&#xff1f; 不支持 三&#xff1a;華為國際版什么時候支持&#xff1f; 2025年預期可以支持。請耐心等待。 三&#xff1a;國際版為什么不支持&#xff1f; EMUI 采用AO…

Spring Boot的啟動流程,以及各個擴展點的執行順序

目錄 1. 初始化階段執行順序 1.1 Bean的構造方法&#xff08;構造函數&#xff09; 1.2 PostConstruct 注解方法 1.3 InitializingBean 的 afterPropertiesSet() 1.4 Bean(initMethod "自定義方法") 2. 上下文就緒后的擴展點 2.1 ApplicationContext 事件監聽…

刀具問題討論

1 刀具的問題概述 問題描述 一道工序用自動化車床連續加工某種零件&#xff0c;由于刀具損壞等原因該工序會出現故障&#xff0c;其中刀具損壞故障占95%, 其它故障僅占 5%。工序出現故障是完全隨機的, 假定在生產任一零件時出現故障的機會均相同。工作人員通過檢查零件來確定…

vite配置一個css插件

vite.config.js的plugins執行函數 該例子只是替換一些css,具體內容不重要,主要看形參的運用 // vite-plugin-css.js export default function cssPlugin() {return {name: vite-plugin-css-post, // 插件的名字&#xff0c;Vite 插件必須有名字enforce: post, // 設定插件執…

?1.1.1 按位與運算替代求余運算優化場景

在計算機編程中&#xff0c;使用按位與運算&#xff08;&&#xff09;替代求余運算&#xff08;%&#xff09;可以提高效率的特殊場景是&#xff1a;當除數是 2 的整數次冪&#xff08;即 ( b 2^n )&#xff0c;其中 ( n ) 為自然數&#xff09;時。例如&#xff0c;( b …

CentOS 7 環境中部署 LNMP(Linux + Nginx + MySQL 5.7 + PHP)

在 CentOS 7 環境中部署 LNMP&#xff08;Linux Nginx MySQL 5.7 PHP&#xff09; 環境的詳細步驟如下。此方案確保各組件版本兼容&#xff0c;并提供完整的配置驗證流程。 1. 更新系統 sudo yum update -y 2. 安裝 MySQL 5.7 2.1 添加 MySQL 官方 YUM 倉庫 由于MySQL并不…

UniApp微信小程序自定義導航欄實現

UniApp微信小程序自定義導航欄 在UniApp開發微信小程序時&#xff0c;頁面左上角默認有一個返回按鈕&#xff08;在導航欄左側&#xff09;&#xff0c;但有時我們需要自定義這個按鈕的樣式和功能&#xff0c;同時保持與導航欄中間的標題和右側膠囊按鈕&#xff08;藥丸屏&…

Java大師成長計劃之第35天:未來展望與個人總結

引言 作為一門歷史悠久的編程語言&#xff0c;Java自1995年問世以來&#xff0c;經歷了多個版本的迭代與演進&#xff0c;依然在當今技術生態中占據著重要地位。從早期的Java SE、Java EE到后來的Java Spring框架&#xff0c;再到現代的微服務架構與云原生應用&#xff0c;Jav…

Ubuntu開機自動運行Docker容器中的Qt UI程序

Ubuntu開機自動運行Docker容器中的Qt UI程序 引言為什么需要這樣配置?解決方案概覽詳細實現步驟1. 創建容器啟動腳本2. 創建系統服務3. 配置自動登錄和顯示設置常見問題解決方案1. 程序無法顯示(X11權限問題)2. 分辨率設置不生效3. 服務啟動失敗安全注意事項結語附錄:完整文…

Scratch節日 | 龍舟比賽 | 端午節

端午節快樂&#xff01; 這款專為孩子們打造的Scratch游戲——《龍舟比賽》&#xff0c;讓你在掌控龍舟的競速中&#xff0c;沉浸式體驗中華傳統節日的魅力&#xff01; &#x1f3ae; 游戲亮點 節日氛圍濃厚&#xff1a;化身龍舟選手&#xff0c;在波濤洶涌的河流中展開刺激競…

(五)MMA(OpenTelemetry/Rabbit MQ/ApiGateway/MongoDB)

文章目錄 項目地址一、OpenTelemetry1.1 配置OpenTelemetry1. 服務添加2. 添加服務標識3. 添加請求的標識4. 添加中間價 二、Rabbit MQ2.1 配置Rabbit MQ1. docker-compose2. 添加Rabbit MQ的Connect String 2.2 替換成Rabbit MQ1. 安裝所需要的包2. 使用 三、API Gateways3.1 …

格恩朗超聲波水表 助力農業精準灌溉與振興?

在農業現代化的征程中&#xff0c;水資源的精準利用至關重要&#xff0c;而這離不開高精度計量設備的支持。大連格恩朗品牌積極響應國家全面推進鄉村振興、加快農業農村現代化的號召&#xff0c;精心打造的超聲波水表&#xff0c;憑借其超高精度&#xff0c;成為綠色灌溉領域的…

微信小程序頁面嵌套web-view點擊系統導航返回時進行彈窗處理

實現效果&#xff1a;微信小程序頁面嵌套web-view點擊系統導航返回時進行彈窗處理 首先在web-view里是不可實現的&#xff08;據我了解下來&#xff09; 參考小程序文檔&#xff1a;page-container 大致邏輯&#xff1a; 1、page-container可實現頁面離開前攔截 2、由于web-vie…

設計模式25——中介者模式

寫文章的初心主要是用來幫助自己快速的回憶這個模式該怎么用&#xff0c;主要是下面的UML圖可以起到大作用&#xff0c;在你學習過一遍以后可能會遺忘&#xff0c;忘記了不要緊&#xff0c;只要看一眼UML圖就能想起來了。同時也請大家多多指教。 中介者模式&#xff08;Mediat…

Java基礎 Day25

一、線程通信 1、簡介 確保線程能夠按照預定的順序執行并且能夠安全地訪問共享資源 使多條線程更好的進行協同工作 2、常用方法 void wait() 使當前線程進入等待狀態 void notify(); 隨機喚醒單個等待的線程&#xff08;可以空喚醒&#xff09; void notifyAll(); 喚醒…