成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

能運(yùn)行,不代表它是對(duì)的:五個(gè)潛伏在正常功能下的 JavaScript 錯(cuò)誤

開發(fā) 前端
JavaScript 是一門看似簡單實(shí)則充滿細(xì)節(jié)的語言,當(dāng)我們開始對(duì)這些“小問題”變得敏感時(shí),代碼質(zhì)量和開發(fā)效率必將邁上一個(gè)新的臺(tái)階。

JavaScript 的動(dòng)態(tài)性和復(fù)雜性意味著,代碼雖然表面上正常運(yùn)行,但一些深層次、隱蔽的陷阱往往讓人意想不到,梳理了幾個(gè) JavaScript 開發(fā)中難以發(fā)現(xiàn)的隱蔽錯(cuò)誤,旨在幫助我們寫出更健壯、更可預(yù)測(cè)的代碼。

來看下那些潛伏在代碼中的“惡魔細(xì)節(jié)”。

1. async/await 的隱式陷阱:忘記 try...catch

async/await 極大地改善了異步代碼的可讀性,但它也帶來了一個(gè)隱蔽的風(fēng)險(xiǎn):未被捕獲的 Promise reject 會(huì)變成一個(gè)靜默的、未處理的異常。

錯(cuò)誤場(chǎng)景:

async function fetchData() {
  // 如果 API 返回 404 或 500,這個(gè) Promise 會(huì)被 reject
  const data = await fetch('https://api.example.com/data');
  console.log('數(shù)據(jù)處理完成', data); // 這一行永遠(yuǎn)不會(huì)執(zhí)行
}

// 調(diào)用函數(shù),但沒有處理潛在的錯(cuò)誤
fetchData(); 
console.log('程序繼續(xù)執(zhí)行'); // 程序會(huì)繼續(xù),但錯(cuò)誤被“吞掉”了

問題根源:await 只是一個(gè)語法糖,它會(huì)暫停 async 函數(shù)的執(zhí)行,等待 Promise 解決。如果 Promise被 reject,await 會(huì)將其作為異常拋出。如果沒有 try...catch 塊來捕獲這個(gè)異常,它就會(huì)沿著調(diào)用棧向上傳播,最終成為一個(gè) unhandledrejection。

正確姿勢(shì):始終用 try...catch 包裹 await 表達(dá)式,或者在調(diào)用鏈的更高層級(jí)進(jìn)行捕獲。

async function fetchData() {
 try {
    const response = await fetch('https://api.example.com/data');
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    const data = await response.json();
    console.log('數(shù)據(jù)處理完成', data);
  } catch (error) {
    console.error('獲取數(shù)據(jù)失敗:', error);
  }
}

fetchData();

2. Promise.all 的“一榮俱榮,一損俱損”

當(dāng)需要并行處理多個(gè) Promise 時(shí),Promise.all 是首選。但高手有時(shí)會(huì)忘記它的“快速失敗”(Fail-Fast)特性。

錯(cuò)誤場(chǎng)景:假設(shè)我們需要獲取用戶詳情和他的帖子列表,即使獲取帖子失敗,也希望看到用戶詳情。

async function getUserProfile(userId) {
  try {
    const [user, posts] = await Promise.all([
      api.fetchUser(userId),       // 這個(gè)成功了
      api.fetchPosts(userId)       // 但這個(gè)因?yàn)榫W(wǎng)絡(luò)問題失敗了
    ]);
    renderProfile(user, posts);
  } catch (error) {
    // 整個(gè) block 都失敗了,我們連 user 數(shù)據(jù)都拿不到
    console.error('獲取用戶 Profile 失敗', error);
  }
}

問題根源:Promise.all 的設(shè)計(jì)是,只要其中任何一個(gè) Promise被 reject,整個(gè) Promise.all 就會(huì)立即 reject,并返回那個(gè)失敗的原因,而不會(huì)等待其他 Promise 完成。

正確姿勢(shì):使用 Promise.allSettled。它會(huì)等待所有 Promise 都有結(jié)果(無論是 fulfilled 還是 rejected),然后返回一個(gè)包含每個(gè) Promise 狀態(tài)和結(jié)果(或原因)的對(duì)象數(shù)組。

async function getUserProfile(userId) {
 const results = await Promise.allSettled([
    api.fetchUser(userId),
    api.fetchPosts(userId)
  ]);

 const userResult = results[0];
 const postsResult = results[1];

 if (userResult.status === 'fulfilled') {
    // 即使帖子失敗,我們依然可以渲染用戶信息
    renderUser(userResult.value);
  } else {
    console.error('獲取用戶失敗:', userResult.reason);
  }

 if (postsResult.status === 'fulfilled') {
    renderPosts(postsResult.value);
  } else {
    console.error('獲取帖子失敗:', postsResult.reason);
  }
}

3. 數(shù)組迭代中的意外突變

在 forEach 或 for...of 循環(huán)中直接修改(增加或刪除)數(shù)組本身,是導(dǎo)致不可預(yù)測(cè)行為的常見原因。

錯(cuò)誤場(chǎng)景:從數(shù)組中移除所有偶數(shù)。

問題根源:當(dāng)你使用 splice 刪除一個(gè)元素時(shí),數(shù)組的長度和后續(xù)元素的索引都會(huì)發(fā)生變化。但 forEach 的迭代過程并不會(huì)根據(jù)這個(gè)變化來調(diào)整它的內(nèi)部計(jì)數(shù)器,導(dǎo)致它跳過緊跟在被刪除元素后面的那個(gè)元素。

正確姿勢(shì):不要在迭代中修改原數(shù)組。最好的方法是創(chuàng)建一個(gè)新數(shù)組。

如果確實(shí)需要在原地修改,請(qǐng)使用反向循環(huán)。

4. 閉包的記憶陷阱與內(nèi)存泄漏

閉包是 JavaScript 的強(qiáng)大特性,但也是內(nèi)存泄漏的主要來源之一,尤其是在處理 DOM 事件監(jiān)聽時(shí)。

錯(cuò)誤場(chǎng)景:

問題根源:即使 element 從 DOM 中移除,只要事件監(jiān)聽器沒有被顯式地移除(removeEventListener),這個(gè)監(jiān)聽器(閉包)就依然存在,并且它會(huì)一直引用著 heavyObject。這導(dǎo)致 heavyObject 和 element 都無法被垃圾回收器回收。

正確姿勢(shì):在組件卸載或元素銷毀時(shí),務(wù)必清理事件監(jiān)聽器。

5. 對(duì)象的深拷貝與淺拷貝之謎

這是一個(gè)永恒的話題。即使是資深開發(fā)者,也可能在不經(jīng)意間對(duì)嵌套對(duì)象進(jìn)行了淺拷貝,導(dǎo)致了意想不到的副作用。

錯(cuò)誤場(chǎng)景:

問題根源:Object.assign() 和展開語法 ... 都只執(zhí)行淺拷貝。它們會(huì)創(chuàng)建一個(gè)新的頂層對(duì)象,但如果屬性值是對(duì)象或數(shù)組,它們只會(huì)復(fù)制引用,而不是值。

正確姿勢(shì):對(duì)于深層嵌套的對(duì)象,需要使用深拷貝,關(guān)于深拷貝可參考前文《一行代碼實(shí)現(xiàn)深拷貝?別再用 JSON.stringify 了!》。

簡單場(chǎng)景 (無函數(shù)、undefined、Symbol等):const deepCopiedProfile = structuredClone(userProfile); // JSON.parse(JSON.stringify(userProfile));

復(fù)雜場(chǎng)景: 使用成熟的庫,如 Lodash 的 _.cloneDeep()。

JavaScript 是一門看似簡單實(shí)則充滿細(xì)節(jié)的語言,當(dāng)我們開始對(duì)這些“小問題”變得敏感時(shí),代碼質(zhì)量和開發(fā)效率必將邁上一個(gè)新的臺(tái)階。

責(zé)任編輯:趙寧寧 來源: JavaScript
相關(guān)推薦

2011-09-28 09:42:44

2015-09-08 13:24:17

2021-12-30 21:51:10

JavaScript開發(fā)內(nèi)存

2021-06-16 15:04:06

JavaScript內(nèi)存開發(fā)

2009-06-30 09:40:00

2010-09-07 09:21:37

2019-03-17 15:14:00

WiFi數(shù)據(jù)泄露黑產(chǎn)

2022-11-17 08:00:18

JavaScript錯(cuò)誤性能

2022-12-15 08:00:38

JavaScript錯(cuò)誤性能

2017-12-21 09:29:47

網(wǎng)絡(luò)運(yùn)行實(shí)踐

2022-04-13 16:25:57

勒索軟件網(wǎng)絡(luò)攻擊

2022-03-10 09:11:33

JavaScrip開發(fā)JSON

2019-10-14 16:39:50

云計(jì)算配置錯(cuò)誤企業(yè)

2024-07-17 13:43:04

2011-08-19 17:18:22

2013-07-22 14:58:53

2015-11-03 08:51:21

程序員怪物

2023-08-18 15:12:00

JavaScript開發(fā)

2023-04-17 16:21:20

JavaScriot前端開發(fā)

2022-01-17 21:37:24

JavaScriptHTMLCSS
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 国产精品18久久久久久白浆动漫 | 免费福利视频一区二区三区 | 日韩在线一区二区三区 | 伊人成人免费视频 | 95国产精品 | 91久久久www播放日本观看 | 欧美a在线观看 | 精品人伦一区二区三区蜜桃网站 | 在线一级片 | caoporn国产精品免费公开 | 欧美日韩一区精品 | 91精品久久久久久久久 | 激情欧美日韩一区二区 | 亚洲一区二区三区四区在线观看 | 国产成人精品一区二区三区视频 | 丝袜一区二区三区 | 成人1区| 九九久久这里只有精品 | 在线免费视频一区 | 国产成人精品高清久久 | 成人深夜福利网站 | 日韩欧美在线不卡 | 亚洲精品电影在线 | 懂色tv | 国产免费拔擦拔擦8x高清 | 亚洲大片在线观看 | 国产成人精品一区二 | 国内精品久久久久久久 | 午夜精品| 国产黄色精品在线观看 | 成人午夜精品一区二区三区 | 在线视频 亚洲 | 韩国av一区二区 | 91国产视频在线观看 | 孕妇一级毛片 | 伊人久久伊人 | 亚洲码欧美码一区二区三区 | 国产一区h | 艹逼网| 91精品在线播放 | 国产成人综合久久 |