對於 JavaScript 中迴圈之間的技術差異概述

前端小智發表於2022-01-17
作者:Gbolahan Olagunju
譯者:前端小智
來源:blog

有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。

本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。

在 JavaScript 中使用迴圈時,需要理解兩個關鍵點:可列舉的屬性可迭代的物件

可列舉的屬性

可列舉物件的一個定義特徵是,當通過賦值操作符向物件分配屬性時,我們將內部 enumerable 標誌設定為true,這是預設值。

當然,我們可以通過將其設定為false來更改此行為。

要點:可列舉的屬性都可以用for...in 遍歷出來。

舉個例子看看:


// 會出現在 for ... in 迴圈中
const gbols = {};
gbols.platform = "LogRocket";

Object.getOwnPropertyDescriptor(gbols, "platform");

// {value: "LogRocket", writable: true, enumerable: true, configurable: true}

for (const item in gbols) {
   console.log(item)
}
// platform


// 不會出現在 for ... in 迴圈中
// 將 enumerable 設定為 false
Object.defineProperty(gbols, 'role', {value: 'Admin', writable: true, enumerable: false})

for (const item in gbols) {
  console.log(item)
}
// platform

可迭代的物件

如果一個物件定義了它的迭代行為,那麼它就是可迭代的。在這種情況下,將在for …of構造中迴圈的值將定義其迭代行為。可迭代的內建型別包括ArraysStringsSetsMapsobject 是不可迭代的,因為它沒有指定@iterator method

在Javascript中,所有可迭代都是可列舉的,但不是所有的可列舉都是可迭代的。

for …in在資料中查詢物件,而for ..of查詢重複序列。來個例子看看:

const authors = ['小智', '小王', '小明', '小紅'];

// 與 for in 迴圈一起使用
fro (const author in authors) {
  console.log(author)
}

// 列印: 0,1,2,3

for (const author of authors) {
  console.log(author)
}

// 列印:小智  小王  小明   小紅

使用此構造時,需要牢記的是,如果呼叫了 typeof 得到的型別是 object,則可以使用for…in迴圈。

我們來看一下對authors變數的操作:

typeof authors

// 列印的是 “object”,因此我們可以使用`for ..in`

乍一看感覺有點奇怪,但必須注意,陣列是一種特殊的物件,它以索引為鍵。for ...in迴圈找到物件時,它將迴圈遍歷每個鍵。

for …in 遍歷 authors 陣列的方式可以用下面顯式化的方式來理解:

const authors = {
  0: 'Jade',
  1: 'Dafe',
  2: 'Gbols',
  3: 'Daniel'
}

重要說明:如果可以追溯到物件(或從物件原型鏈繼承它),因為for …in將以不特定的順序遍歷鍵。

同時,如果實現 for.. of 構造的迭代器,則它將在每次迭代中迴圈遍歷該值。

ForEach 和 map 方法

儘管可以使用forEachmap方法來實現相同的目標,但是它們的行為和效能方面存在差異。

基礎層面上,當函式被呼叫時,它們都接收一個回撥函式作為引數。

考慮下面的程式碼片段:

const scoresEach = [2,4 ,8, 16, 32];
const scoresMap = [2,4 ,8, 16, 32];
const square = (num) => num * num;

我們逐一列出其操作上的一些差異。

forEach返回undefined,而map返回一個新陣列:

let newScores = []
const resultWithEach = scoresEach.forEach((score) => {
const newScore = square(score);
newScores.push(newScore);
});
const resultWithMap = scoresMap.map(square);

console.log(resultWithEach) // undefined
console.log(resultWithMap) // [4, 16, 64, 256, 1024]

map是一個純函式,而forEach則執行一些更改:

console.log(newScores) // [4, 16, 64, 256, 1024]

在我看來,map傾向於函數語言程式設計範例。與forEach不同的是,我們並不總是需要執行一次更改來獲得想要的結果,在forEach中,我們需要對newscore變數進行更改。在每次執行時,當提供相同的輸入時,map函式將產生相同的結果。同時,forEach對應項將從最後一次更改的前一個值中獲取資料。

鏈式

map可以使用鏈式操作,因為map返回的結果是一個陣列。因此,可以立即對結果呼叫任何其他陣列方法。換句話說,我們可以呼叫filter, reduce, some等等。對於forEach,這是不可能的,因為返回的值是undefined

效能

map 方法的效能往往優於forEach方法。

檢查用mapforEach實現的等效程式碼塊的效能。平均而言,map函式的執行速度至少要快50%

注意:此基準測試取決於你使用的計算機以及瀏覽器的實現。

總結

在上面討論的所有迴圈結構中,為我們提供最多控制的是for..of的迴圈。我們可以將它與關鍵字returncontinuebreak一起使用。這意味著我們可以指定我們希望對陣列中的每個元素髮生什麼,以及我們是想早點離開還是跳過。

原文:https://medium.com/better-pro...

程式碼部署後可能存在的BUG沒法實時知道,事後為了解決這些BUG,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug

交流

有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。

本文 GitHub https://github.com/qq44924588... 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。

相關文章