日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

代碼速度慢?避免這 19 種常見的 JavaScript 和 Node.js 錯誤

來源: 責編: 時間:2023-11-03 09:16:24 286觀看
導讀譯者 | 劉汪洋審校 | 重樓速度、性能和響應性在 Web 開發中起著至關重要的作用,尤其是在使用 JavaScript 和 Node.js 開發時尤為重要。如果一個網站響應緩慢或界面卡頓,就會讓人感到非常業余;如果網站經過精心設計和優化

譯者 | 劉汪洋p4728資訊網——每日最新資訊28at.com

審校 | 重樓p4728資訊網——每日最新資訊28at.com

速度、性能和響應性在 Web 開發中起著至關重要的作用,尤其是在使用 JavaScript 和 Node.js 開發時尤為重要。如果一個網站響應緩慢或界面卡頓,就會讓人感到非常業余;如果網站經過精心設計和優化,能夠給用戶帶來絲滑的使用體驗,就顯得非常專業。p4728資訊網——每日最新資訊28at.com

p4728資訊網——每日最新資訊28at.com

打造一個真正高性能的 Web 應用并非易事,其中潛藏著許多容易忽視的性能陷阱。這些不易被察覺的編程習慣或錯誤不僅可能降低 JavaScript 的執行速度,還可能導致代碼冗余,進一步降低應用的運行效率。p4728資訊網——每日最新資訊28at.com

即使你已經壓縮了代碼并合理地使用了緩存,網站在某些情況下仍然可能運行緩慢。例如,用戶界面在滾動或點擊按鈕時出現明顯的卡頓,或頁面加載時間過長。p4728資訊網——每日最新資訊28at.com

這到底是為什么呢?p4728資訊網——每日最新資訊28at.com

分析表明,有多種常見的不良實踐會無意中拖慢 JavaScript 的執行效率。隨著時間推移,這些不良實踐會逐步影響網站的整體性能。p4728資訊網——每日最新資訊28at.com

幸運的是,這些性能問題都是可以預防和解決的。p4728資訊網——每日最新資訊28at.com

本文將深入分析 19 個可能降低 JavaScript 和 Node.js 應用性能的隱性問題,并通過具體的實例和解決策略,對這些問題進行詳細討論和優化。p4728資訊網——每日最新資訊28at.com

準確地識別并解決這些性能陷阱是實現高效、流暢用戶體驗的關鍵。下面,就讓我們一起探索吧!p4728資訊網——每日最新資訊28at.com

1. 變量聲明與作用域的不恰當使用

在 JavaScript 初學階段,開發者常常習慣性地在全局作用域中聲明變量,但這種做法往往會帶來很多副作用。
讓我們通過一個示例來解釋:p4728資訊網——每日最新資訊28at.com

// globals.jsvar color = 'blue';function printColor() {  console.log(color); }printColor(); // 輸出 'blue'

雖然上述代碼看著沒有問題,但如果有另一個腳本中編寫如下代碼:p4728資訊網——每日最新資訊28at.com

// script2.jsvar color = 'red';printColor(); // 輸出 'red'!

由于 color 變量是在全局作用域內定義的,因此 script2.js 就能夠輕易覆蓋它。為避免這種情況,應盡量在函數作用域內聲明局部變量:p4728資訊網——每日最新資訊28at.com

function printColor() {  var color = 'blue'; // 局部變量    console.log(color);}printColor(); // 輸出 'blue'

這樣一來,其他腳本中對全局變量的更改不會影響 printColor 函數。p4728資訊網——每日最新資訊28at.com

在全局作用域內隨意聲明變量是一種不良的編程習慣,也被認為是編程反模式。應當盡量將全局變量的使用局限于配置常量,并確保其他變量在盡可能小的作用域內被聲明。p4728資訊網——每日最新資訊28at.com

2. DOM 操作的效率問題

在更新 DOM 元素時,建議批量更改,而不是一次只操作一個節點。
請看以下逐個添加列表項的代碼示例:p4728資訊網——每日最新資訊28at.com

const ul = document.getElementById('list');for (let i = 0; i < 10; i++) {  const li = document.createElement('li');  li.textContent = i;    ul.appendChild(li);}

更好的做法是先構建一個字符串,然后通過 .innerHTML進行設置:p4728資訊網——每日最新資訊28at.com

const ul = document.getElementById('list');let html = '';for (let i = 0; i < 10; i++) {  html += `<li>${i}</li>`; }ul.innerHTML = html;

構建字符串可以減少回流。我們只需一次更新 DOM,而不是十次。p4728資訊網——每日最新資訊28at.com

對于多次更新,可以先集中收集所有的更改,然后一次性地應用。或者更好的辦法是使用 DocumentFragment 進行批量節點添加。p4728資訊網——每日最新資訊28at.com

3. DOM 操作的過度使用

過于頻繁地更新 DOM 會對性能產生嚴重影響。
以一個聊天應用為例,該應用將每條新消息插入到頁面中。p4728資訊網——每日最新資訊28at.com

不推薦的做法:

// 收到新消息const msg = `<div>${messageText}</div>`;chatLog.insertAdjacentHTML('beforeend', msg);

這種方法會在每收到一條新消息時直接進行 DOM 插入。
一個更加高效的方法是限制更新的頻率:p4728資訊網——每日最新資訊28at.com

推薦的做法:

let chatLogHTML = '';const throttleTime = 100; // ms// 收到新消息chatLogHTML += `<div>${messageText}</div>`;// 對 DOM 更新進行節流setTimeout(() => {  chatLog.innerHTML = chatLogHTML;  chatLogHTML = ''; }, throttleTime);

通過這種方式,我們最多每 100ms 執行一次 DOM 更新,有效地控制了更新操作的頻率。p4728資訊網——每日最新資訊28at.com

對于高度動態的用戶界面,可考慮使用如 React 等支持虛擬 DOM 的庫。這些庫能通過虛擬表示來最小化實際的 DOM 操作。p4728資訊網——每日最新資訊28at.com

4. 事件委托的缺失

給多個元素分別添加事件監聽器會導致不必要的資源消耗。例如,一個表格,其中每一行都有一個刪除按鈕:p4728資訊網——每日最新資訊28at.com

不推薦的實踐:

const rows = document.querySelectorAll('table tr');rows.forEach(row => {  const deleteBtn = row.querySelector('.delete');    deleteBtn.addEventListener('click', handleDelete);});

這種方式為每一個刪除按鈕都單獨設置了一個事件監聽器。更優的做法是采用事件委托機制:p4728資訊網——每日最新資訊28at.com

推薦的實踐:

const table = document.querySelector('table');table.addEventListener('click', e => {  if (e.target.classList.contains('delete')) {    handleDelete(e);  }});

采用這種方式后,整個 <table> 元素僅需一個事件監聽器,從而降低了內存消耗。p4728資訊網——每日最新資訊28at.com

事件委托是通過利用事件冒泡,讓單一的事件監聽器管理多個事件。應該在合適的情況下使用委托。p4728資訊網——每日最新資訊28at.com

5. 字符串拼接的低效性

在循環中進行字符串拼接會影響性能。
看看下面的代碼:p4728資訊網——每日最新資訊28at.com

let html = '';for (let i = 0; i < 10; i++) {  html += '<div>' + i + '</div>';}

創建新字符串需要內存分配。為了提高性能,更有效的做法是使用數組:p4728資訊網——每日最新資訊28at.com

const parts = [];for (let i = 0; i < 10; i++) {  parts.push('<div>', i, '</div>');}const html = parts.join('');

使用數組能減少中間字符串的生成。.join() 方法在最后進行一次性的拼接。p4728資訊網——每日最新資訊28at.com

對于多次字符串拼接,使用數組的 join 方法。同時,也可以考慮使用模板字面量來嵌入變量。p4728資訊網——每日最新資訊28at.com

6. 循環性能未經優化

在 JavaScript 中,循環常常是性能問題的罪魁禍首。一個常見的錯誤是反復獲取數組長度:p4728資訊網——每日最新資訊28at.com

不佳實踐:

const items = [/*...*/];for (let i = 0; i < items.length; i++) {  // ...}

重復檢查 .length 會阻礙優化。p4728資訊網——每日最新資訊28at.com

優秀實踐:p4728資訊網——每日最新資訊28at.com

const items = [/*...*/];const len = items.length;for (let i = 0; i < len; i++) {  // ...}

通過緩存數組長度,我們可以避免在每次迭代中都去計算它,從而提高循環速度。其他優化手段包括從循環中提升不變量,簡化終止條件,以及避免在迭代中進行耗時較長的操作。p4728資訊網——每日最新資訊28at.com

7. 不必要的同步操作

JavaScript 的異步能力是其一大優點。但要警惕阻塞式 I/O!p4728資訊網——每日最新資訊28at.com

例如:p4728資訊網——每日最新資訊28at.com

不佳實踐:

const data = fs.readFileSync('file.json'); // 阻塞!

這會在從磁盤讀取數據時暫停執行。相反,應使用回調或 Promise:p4728資訊網——每日最新資訊28at.com

優秀實踐:

fs.readFile('file.json', (err, data) => {  // ...});

現在,在文件讀取過程中,事件循環仍然會繼續執行。對于復雜的流程,async/await 可以簡化異步邏輯。要避免使用同步操作以防止阻塞。p4728資訊網——每日最新資訊28at.com

8. 阻塞事件循環

JavaScript 使用單線程的事件循環。阻塞它會導致整個程序暫停執行。常見的阻塞因素包括:p4728資訊網——每日最新資訊28at.com

  • 大量的計算任務
  • 同步 I/O
  • 未優化的算法

例如:p4728資訊網——每日最新資訊28at.com

function countPrimes(max) {  // 未優化的循環  for (let i = 0; i <= max; i++) {    // ...檢查是否為質數...  }}countPrimes(1000000); // 長時間運行!

這樣的代碼會同步執行,從而阻塞其他事件。為了避免這種情況,你可以:p4728資訊網——每日最新資訊28at.com

  • 延遲不必要的任務
  • 批量處理數據
  • 使用 Worker 線程
  • 尋找代碼優化的機會

要確保事件循環可以流暢地運行。定期進行性能分析以捕獲阻塞性代碼。p4728資訊網——每日最新資訊28at.com

9. 低效的錯誤處理

在 JavaScript 中,正確地處理錯誤是至關重要的。但要小心性能陷阱!p4728資訊網——每日最新資訊28at.com

不佳實踐:

try {  // ...} catch (err) {  console.error(err); // 僅僅是記錄}

這樣雖然捕獲了錯誤,但并未采取糾正措施。未處理的錯誤通常會導致內存泄漏或數據損壞。p4728資訊網——每日最新資訊28at.com

更佳實踐:

try {  // ...} catch (err) {  console.error(err);    // 觸發錯誤事件  emitError(err);     // 將變量置為空  obj = null;    // 通知用戶  showErrorNotice();}

單純記錄錯誤是不夠的!要清理殘留數據,通知用戶,并考慮恢復選項。使用像 Sentry 這樣的工具來監控生產環境中的錯誤,并明確處理所有錯誤。p4728資訊網——每日最新資訊28at.com

11. 內存泄漏

內存泄漏是當內存被分配但從未被釋放的情況。隨著時間的推移,泄漏會累積并降低性能。p4728資訊網——每日最新資訊28at.com

在 JavaScript 中,常見的內存泄漏來源包括:p4728資訊網——每日最新資訊28at.com

  • 未清理的事件監聽器
  • 過時的對已刪除 DOM 節點的引用
  • 不再需要的緩存數據
  • 在閉包中累積的狀態

例如:p4728資訊網——每日最新資訊28at.com

function processData() {  const data = [];  // 使用閉包累積數據  return function() {    data.push(getData());   }}const processor = processData();// 長時間運行...持續持有對不斷增長的數據數組的引用!

這個數組持續變大,但從未被清理。要修復這個問題,你可以:p4728資訊網——每日最新資訊28at.com

  • 使用弱引用
  • 清理事件監聽器
  • 刪除不再需要的引用
  • 限制閉包狀態的大小

持續監控內存使用情況,并關注其增長趨勢。在問題積累之前,主動消除內存泄漏。p4728資訊網——每日最新資訊28at.com

12. 過度依賴外部庫

NPM (Node Package Manager) 提供了大量的庫和工具,讓開發者可以選擇和使用,但應避免不加考慮地導入過多的依賴!每增加一個依賴,都會增加包的大小和潛在的攻擊面。p4728資訊網——每日最新資訊28at.com

不佳做法:

import _ from 'lodash';import moment from 'moment'; import validator from 'validator';// 等等...

僅為了一些小功能就導入整個庫。更好的做法是按需選擇性地導入所需的函數:p4728資訊網——每日最新資訊28at.com

良好做法:

import cloneDeep from 'lodash/cloneDeep';import { format } from 'date-fns';import { isEmail } from 'validator';

只導入你真正需要用到的功能。定期審查依賴,剔除不再使用的庫。保持項目依賴精簡,盡量減少不必要的庫和工具。p4728資訊網——每日最新資訊28at.com

13. 沒有充分利用緩存

緩存能夠通過重用之前的結果,以避免重復進行耗時的計算,但人們常常忽視這一點。p4728資訊網——每日最新資訊28at.com

不佳做法:

function generateReport() {  // 執行耗時的處理過程  // 以生成報告數據...}generateReport(); // 計算一次generateReport(); // 再次計算!

由于輸入沒有改變,報告完全可以被緩存:p4728資訊網——每日最新資訊28at.com

良好做法:

let cachedReport;function generateReport() {  if (cachedReport) {    return cachedReport;  }  cachedReport = // 耗時的處理...  return cachedReport; }

現在,重復的函數調用會很快。其他的緩存策略:p4728資訊網——每日最新資訊28at.com

  • 像 Redis 這樣的內存緩存
  • HTTP 緩存頭
  • 用于客戶端緩存的 LocalStorage
  • 用于資產緩存的 CDN

對適合緩存的數據進行緩存,通常會顯著提升速度!p4728資訊網——每日最新資訊28at.com

14. 未優化的數據庫查詢

在與數據庫交互時,低效的查詢會拖慢性能。應避免的問題有:p4728資訊網——每日最新資訊28at.com

不佳做法:

// 沒有使用索引db.find({name: 'John', age: 35}); // 查詢不必要的字段db.find({first: 'John', last:'Doe', email:'john@doe.com'}, {first: 1, last: 1});// 過多的獨立查詢for (let id of ids) {  const user = db.find({id});}

這樣做沒有利用到索引、檢索了不需要的字段,還進行了大量不必要的查詢。p4728資訊網——每日最新資訊28at.com

良好做法:

// 在 'name' 上使用索引db.find({name: 'John'}).hint({name: 1});// 只獲取 'email' 字段db.find({first: 'John'}, {email: 1}); // 一次查詢獲取多個用戶const users = db.find({  id: {$in: ids} });

分析并解釋查詢計劃,有針對性地創建索引,避免分散的多次查詢,優化與數據存儲的交互。p4728資訊網——每日最新資訊28at.com

15. 不恰當的 Promise 錯誤處理

Promises 簡化了異步代碼,但如果拒絕沒有得到處理,就會靜默地失敗。p4728資訊網——每日最新資訊28at.com

不佳的做法:

function getUser() {  return fetch('/user')    .then(r => r.json());}getUser();

如果 fetch 拒絕,異常將不會被注意到。p4728資訊網——每日最新資訊28at.com

良好的做法:p4728資訊網——每日最新資訊28at.com

function getUser() {  return fetch('/user')    .then(r => r.json())    .catch(err => console.error(err));}getUser();

通過鏈接 .catch() 來恰當地處理錯誤。其他建議:p4728資訊網——每日最新資訊28at.com

  • 避免 Promise 嵌套地獄
  • 在最頂層處理拒絕
  • 配置未處理拒絕的跟蹤

不要忽視 Promise 的錯誤!p4728資訊網——每日最新資訊28at.com

16. 同步的網絡操作

網絡請求應當是異步的。但有時會使用同步版本:p4728資訊網——每日最新資訊28at.com

不佳的做法:

const data = http.getSync('http://example.com/data'); // 阻塞!

這將在請求期間暫停事件循環。應使用回調函數:p4728資訊網——每日最新資訊28at.com

良好的做法:

http.get('http://example.com/data', res => {  // ...});

或者使用 Promises:p4728資訊網——每日最新資訊28at.com

fetch('http://example.com/data')  .then(res => res.json())  .then(data => {    // ...  });

異步的網絡請求允許在等待響應時進行其他處理。避免使用同步網絡調用。p4728資訊網——每日最新資訊28at.com

17. 文件 I/O 操作的低效性

同步地讀取/寫入文件會造成阻塞。例如:p4728資訊網——每日最新資訊28at.com

糟糕的做法:

const contents = fs.readFileSync('file.txt'); // 阻塞!

這會在磁盤 I/O 期間暫停程序執行。更好的方式是:p4728資訊網——每日最新資訊28at.com

良好的做法:

fs.readFile('file.txt', (err, contents) => {  // ...});// 或者使用 Promisefs.promises.readFile('file.txt')   .then(contents => {     // ...     });

這樣做使得在讀取文件期間,事件循環能夠繼續運行。p4728資訊網——每日最新資訊28at.com

對于多個文件,應使用流:p4728資訊網——每日最新資訊28at.com

function processFiles(files) {  for (let file of files) {    fs.createReadStream(file)      .pipe(/*...*/);  }}

避免使用同步文件操作。應優先使用回調、Promise 和流。p4728資訊網——每日最新資訊28at.com

18. 忽略性能分析和優化

性能問題往往在明顯出現之前容易被忽視。然而,優化應該是一個持續的過程!首先,應使用性能分析工具進行測量:p4728資訊網——每日最新資訊28at.com

  • 瀏覽器開發者工具時間線
  • Node.js 分析器
  • 第三方性能分析工具

即便性能看似正常,這些工具也能揭示一些優化的機會:p4728資訊網——每日最新資訊28at.com

// profile.jsfunction processOrders(orders) {  orders.forEach(o => {    // ...  });}processOrders(allOrders);

分析器顯示 processOrders 函數耗時 200ms。經過調查,我們發現:p4728資訊網——每日最新資訊28at.com

  • 循環沒有優化
  • 內部操作耗時高
  • 存在不必要的工作

我們逐步進行優化,最終版本僅需 5ms!p4728資訊網——每日最新資訊28at.com

性能分析是優化的指導方針。應設立性能閾值,并在超過閾值時觸發告警。應經常進行性能測試,并謹慎地進行優化。p4728資訊網——每日最新資訊28at.com

19. 不必要的代碼重復

代碼重復不僅影響維護性,還降低了優化空間??紤]以下例子:p4728資訊網——每日最新資訊28at.com

function userStats(user) {  const name = user.name;  const email = user.email;    // ...邏輯...}function orderStats(order) {  const name = order.customerName;  const email = order.customerEmail;  // ...邏輯... }

這里的信息提取邏輯是重復的。我們進行重構:p4728資訊網——每日最新資訊28at.com

function getCustomerInfo(data) {  return {    name: data.name,     email: data.email  };}function userStats(user) {  const { name, email } = getCustomerInfo(user);    // ...邏輯...}function orderStats(order) {  const { name, email } = getCustomerInfo(order);  // ...邏輯...}

現在,相同的邏輯只定義了一次。其他可行的修復措施包括:p4728資訊網——每日最新資訊28at.com

  • 提取實用函數
  • 創建輔助類
  • 利用模塊實現重用性

盡量避免代碼重復,這樣既能提高代碼質量,也能提供更多優化的機會。p4728資訊網——每日最新資訊28at.com

結論

優化 JavaScript 應用性能是一個持續迭代的任務。通過掌握高效的編程方法和不斷地進行性能評估,能夠明顯提升網站的運行速度。p4728資訊網——每日最新資訊28at.com

特別需要關注的幾個核心方面包括:降低 DOM 的修改頻率、運用異步技術、避免阻塞性操作、精簡依賴、利用數據緩存,以及消除冗余代碼。p4728資訊網——每日最新資訊28at.com

隨著專注度和實踐經驗的不斷積累,你將能有效地定位到性能瓶頸,并針對特定業務場景進行有針對性的優化。這樣一來,你將構建出更快、更簡潔和響應更敏捷的 Web 應用,從而贏得用戶的青睞。p4728資訊網——每日最新資訊28at.com

總之,在性能優化的路上,不能有絲毫的大意。遵循這些優化建議,你會發現你的 JavaScript 代碼執行速度得到了顯著提升。p4728資訊網——每日最新資訊28at.com

原文標題:Is Your Code Slow?: Avoid These 19 Common JavaScript and Node.js Mistakes,作者:JSDevJournalp4728資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-16729-0.html代碼速度慢?避免這 19 種常見的 JavaScript 和 Node.js 錯誤

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 了不起的Unicode

下一篇: Golang 中的 Strconv 包詳解,看這篇就夠了

標簽:
  • 熱門焦點
Top 主站蜘蛛池模板: 长顺县| 札达县| 固镇县| 胶州市| 华容县| 西峡县| 贵港市| 交城县| 仙桃市| 孙吴县| 长武县| 青冈县| 昌邑市| 习水县| 深州市| 当雄县| 宣化县| 霍州市| 巴林右旗| 莱阳市| 临泽县| 汝州市| 新巴尔虎左旗| 彭水| 德格县| 北宁市| 洛川县| 镇远县| 霍城县| 晋州市| 仙游县| 定襄县| 蓬安县| 永泰县| 盐边县| 遂溪县| 古交市| 兴宁市| 浪卡子县| 七台河市| 靖西县|