踩坑經驗:JavaScript 中的 for...of 和 for...in 循環

在 JavaScript 編程中,for...offor...in 是常用的循環語法,但它們在使用時可能會引發一些意想不到的問題。本文將分享我在使用這兩種循環時所遇到的坑和經驗。

兩者的區別:

  1. 適用對象類型
    • for…of:主要用于遍歷可迭代對象(例如數組、字符串、Set、Map等),可以獲取到迭代對象的值。
    • for…in:主要用于遍歷對象的屬性(包括原型鏈上的屬性),可以獲取到屬性名(鍵)。
  1. 遍歷順序
    • for…of:按照對象的順序迭代,一般用于遍歷有序集合。
    • for…in:無法保證屬性的遍歷順序,可能會導致屬性的無序輸出。
  1. 迭代內容
    • for…of:迭代的是對象的值本身,例如數組中的元素、字符串中的字符等。
    • for…in:迭代的是對象的屬性名,需要通過屬性名訪問屬性值。
  1. 支持情況
    • for…of:在 ES6 中引入,適用于可迭代對象,如數組、字符串等。
    • for…in:在早期版本的 JavaScript 中就存在,用于遍歷對象的屬性。但是不適用于數組等可迭代對象,因為它會遍歷出額外的屬性。
  1. 性能
    • for…of:通常性能比 for…in 更好,因為它不需要遍歷原型鏈上的屬性。

示例代碼演示兩者的不同用法:

// for...of 遍歷數組
const arr = [1, 2, 3, 4];
for (const element of arr) {console.log(element); // 輸出數組的每個元素
}// for...in 遍歷對象的屬性
const obj = { a: 1, b: 2, c: 3 };
for (const key in obj) {console.log(key);      // 輸出屬性名 a, b, cconsole.log(obj[key]); // 輸出屬性值 1, 2, 3
}// for...of 遍歷數組
const arr = [1, 2, 3, 4];
for (const element of arr) {console.log(element); // 輸出數組的每個元素
}// for...in 遍歷對象的屬性
const obj = { a: 1, b: 2, c: 3 };
for (const key in obj) {console.log(key);      // 輸出屬性名 a, b, cconsole.log(obj[key]); // 輸出屬性值 1, 2, 3
}

總之,如果你想遍歷數組或其他可迭代對象的值,使用 for…of;如果你想遍歷對象的屬性,使用 for…in

for…of 遍歷數組的陷阱:

當使用 for...of 循環來遍歷數組時,我們通常是為了遍歷數組的元素,而不是索引。然而,在使用 for...of 循環時,有一些常見陷阱需要避免,特別是關于循環索引和遍歷順序的問題。下面是如何正確使用 for...of 循環來遍歷數組,以及如何避免這些陷阱的解釋:

1. 遍歷元素而非索引: 使用 for...of 循環時,我們直接遍歷數組的元素,而不需要關心索引的細節。這樣可以使代碼更加簡潔易讀。例如:


const array = [1, 2, 3, 4, 5];
for (const element of array) {console.log(element); // 輸出數組的每個元素
}

2. 避免使用索引: 避免在 for...of 循環中使用額外的索引變量,因為 for...of 循環本身已經直接提供了數組的每個元素。這有助于減少代碼復雜性和錯誤的機會。不推薦的寫法:


const array = [1, 2, 3, 4, 5];
for (let i = 0; i < array.length; i++) {console.log(array[i]); // 避免這種額外使用索引的方式
}

3. 保持遍歷順序: for...of 循環保證按照數組中的順序進行遍歷,因此它適用于需要按順序處理元素的場景。這確保了元素的處理順序與它們在數組中的位置一致。

4. 不會遍歷稀疏元素: for...of 循環不會遍歷數組中的稀疏元素(未賦值的元素),只會遍歷有實際值的元素。這有助于避免不必要的處理。

5. 適用于可迭代對象: 除了數組,for...of 循環還適用于其他可迭代對象,如字符串、Set、Map 等。這使得代碼具有更廣泛的適用性。

綜上所述,使用 for...of 循環來遍歷數組是一種更直觀、簡潔的方式,可以避免許多在傳統 for 循環中容易犯的錯誤。通過專注于元素而非索引,保持遍歷順序,并充分利用循環的簡潔性,我們可以提高代碼的可讀性和可維護性,減少錯誤的風險。

for…in 遍歷對象的不可靠性:

在使用 for...in 循環時,可能會遇到一些問題,其中包括遍歷順序的不確定性和遍歷到原型屬性的風險。下面是對這些問題的探討:

1. 遍歷順序的不確定性: for...in 循環無法保證遍歷對象屬性的順序。這是因為對象屬性在 ECMAScript 規范中被定義為無序的。因此,使用 for...in 循環來依賴屬性遍歷的特定順序是不可靠的。

2. 遍歷到原型屬性的風險: for...in 循環會遍歷對象自身屬性以及繼承自原型鏈的屬性。這可能會導致意外的屬性遍歷,尤其是當我們只想遍歷對象自身的屬性時。

3. 原型屬性被遍歷:


function Person() {this.name = 'Alice';
}Person.prototype.age = 30;const person = new Person();for (const prop in person) {console.log(prop); // 輸出 'name' 和 'age'
}

/*** @param {Function} fn* @return {Array}*/
array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
fn = function (n) {return String(n > 5);
}Array.prototype.groupBy = function (fn) {const myMap = new Map();const keys = Object.keys(this);console.log(keys);for (const key in keys) {if (myMap.has(fn(this[key]))) {myMap.set(fn(this[key]), myMap.get(fn(this[key])).concat([this[key]]));} else {myMap.set(fn(this[key]), [this[key]]);}}const myObj = {};for (const [key, value] of myMap) {myObj[key] = value;}return myObj;
};array.groupBy(fn);
/*** [1,2,3].groupBy(String) // {"1":[1],"2":[2],"3":[3]}*/

image.png

image.png
4. 使用 hasOwnProperty 過濾原型屬性:


for (const prop in person) {if (person.hasOwnProperty(prop)) {console.log(prop); // 僅輸出 'name'}
}

5. 遍歷可枚舉屬性:


Object.defineProperty(person, 'country', {value: 'USA',enumerable: true
});for (const prop in person) {console.log(prop); // 輸出 'name'、'age' 和 'country'
}

6. 遍歷不可枚舉屬性:


Object.defineProperty(person, 'address', {value: '123 Main St',enumerable: false
});for (const prop in person) {console.log(prop); // 僅輸出 'name' 和 'age'
}

7. 遍歷順序問題:


const obj = { a: 1, b: 2, c: 3 };for (const prop in obj) {console.log(prop); // 輸出 'a'、'b' 和 'c',但順序不確定
}

8. 遍歷字符串屬性:


const str = 'Hello';for (const char in str) {console.log(char); // 輸出 '0'、'1'、'2'、'3' 和 '4'
}

綜上所述,盡管 for...in 循環在某些情況下可以派上用場,但要特別小心遍歷順序的不確定性和遍歷到原型屬性的風險。在需要遍歷對象屬性時,推薦使用 Object.keysObject.valuesObject.entries 等方法,以獲得更可靠的遍歷結果。或者,考慮使用 for...of 循環來遍歷數組和可迭代對象,以避免這些問題。

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

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

相關文章

數據結構-帶頭雙向循環鏈表的實現

前言 帶頭雙向循環鏈表是一種重要的數據結構&#xff0c;它的結構是很完美的&#xff0c;它彌補了單鏈表的許多不足&#xff0c;讓我們一起來了解一下它是如何實現的吧&#xff01; 1.節點的結構 它的節點中存儲著數據和兩個指針&#xff0c;一個指針_prev用來記錄前一個節點…

Git詳解及使用

Git簡介 Git 是一種分布式版本控制系統&#xff0c;它可以不受網絡連接的限制&#xff0c;加上其它眾多優點&#xff0c;目前已經成為程序開發人員做項目版本管理時的首選&#xff0c;非開發人員也可以用 Git 來做自己的文檔版本管理工具。 大概是大二的時候開始接觸和使用Gi…

云計算——ACA學習 云計算核心技術

作者簡介&#xff1a;一名云計算網絡運維人員、每天分享網絡與運維的技術與干貨。 座右銘&#xff1a;低頭趕路&#xff0c;敬事如儀 個人主頁&#xff1a;網絡豆的主頁????? 寫在前面 本系列將會持續更新云計算阿里云ACA的學習&#xff0c;了解云計算及網絡安全相關…

DeepSpeed加速大模型訓練

DeepSpeed是微軟推出的一個框架&#xff0c;可以對Pytorch的模型進行包裝&#xff0c;提供了加快模型的訓練速度&#xff0c;降低對GPU顯存的占用&#xff0c;以及方便進行分布式訓練等等高級特性。在這里我也對DeepSpeed進行了測試&#xff0c;看看是否能提高我的transformer模…

Maven 插件 maven-antrun-plugin 執行 ant 腳本

Ant 相信大家都不陌生&#xff0c;你可以把它理解為使用 xml 格式描述的一系列命令處理工具。它是一種基于Java的build工具。理論上來說&#xff0c;它有些類似于&#xff08;Unix&#xff09;C中的make、有些類似于基于shell命令編寫的sh腳本文件。Ant 用 Java 的類來擴展。&a…

多維時序 | MATLAB實現PSO-CNN-BiLSTM多變量時間序列預測

多維時序 | MATLAB實現PSO-CNN-BiLSTM多變量時間序列預測 目錄 多維時序 | MATLAB實現PSO-CNN-BiLSTM多變量時間序列預測基本介紹模型特點程序設計參考資料 基本介紹 本次運行測試環境MATLAB2021b&#xff0c;MATLAB實現PSO-CNN-BiLSTM多變量時間序列預測。代碼說明&#xff1a…

Java mail郵件開發 OA辦公系統

目錄 1 Java mail郵件開發 OA辦公系統 1.1 //用戶登錄 1.2 //用戶注冊 1.3 //根據郵箱賬號查詢用戶ID Java mail郵件開發 OA辦公系統package com.email.dao.impl; import java.sql.Connection; import java.sql.PreparedStatement;<

POSTGRESQL 關于2023-08-14 數據庫自動啟動文章中使用KILL 來進行配置RELOAD的問題解釋...

開頭還是介紹一下群&#xff0c;如果感興趣Polardb ,mongodb ,MySQL ,Postgresql ,redis &#xff0c;SQL SERVER ,ORACLE,Oceanbase 等有問題&#xff0c;有需求都可以加群群內有各大數據庫行業大咖&#xff0c;CTO&#xff0c;可以解決你的問題。加群請加 liuaustin3微信號 &…

Oracle執行計劃

Oracle執行計劃 1. 什么是執行計劃Oracle explain使用3. Explain執行順序 1. 什么是執行計劃 執行計劃是一條查詢語句在Oracle中的執行過程或訪問路徑的描述。 執行計劃描述了SQL引擎為執行SQL語句進行的操作&#xff1b;分析SQL語句相關的性能問題或僅僅質疑查詢優化器的決定…

蔚來李斌賣手機:安卓系統,蘋果售價,一年一發

?作者 | Amy 編輯 | 德新 車圈大佬的玩法真讓人尋不著套路&#xff01; 蘋果的庫克和小米的雷布斯&#xff0c;甚至是FF賈老板準備許久&#xff0c;都想分一塊新能源車的蛋糕&#xff0c;蔚來李斌卻反手進軍手機界&#xff0c;從宣布造手機到手機入網僅僅隔了一年。 近期…

說幾個常見的語法糖

目錄 面試回答 知識擴展 如何解語法糖&#xff1f; 糖塊一、swith 支持 String 與枚舉 糖塊二、泛型 糖塊三、自動裝箱與拆箱 糖塊四、枚舉 糖塊五、條件編譯 糖塊六、斷言 糖塊七、數值字面量 糖塊八、for-each 糖塊九、try-with-resource 可能遇到的坑 泛型 自…

Beats:安裝及配置 Metricbeat (一)- 8.x

在我之前的文章&#xff1a; Beats&#xff1a;Beats 入門教程 &#xff08;一&#xff09;Beats&#xff1a;Beats 入門教程 &#xff08;二&#xff09; 我詳細描述了如何在 Elastic Stack 7.x 安裝及配置 Beats。在那里的安裝&#xff0c;它通常不帶有安全及 Elasticsearc…

MapReduce介紹

目錄 ?一、什么是MapReduce 二、MapReduce 的設計思想 2.1 分而治之 2.2 構建抽象模型&#xff1a;Map和Reduce 2.3 隱藏系統層細節 三、MapReduce 的框架原理 3.1 MRv1工作原理 3.1.1 MRv1架構工作原理圖 3.1.1.1 流程說明 3.1.1.1.1 作業的提交 3.1.1.1.2 作業的初始化 3…

【AI大模型】訓練Al大模型 (上篇)

大模型超越AI 前言 潔潔的個人主頁 我就問你有沒有發揮&#xff01; 知行合一&#xff0c;志存高遠。 目前所指的大模型&#xff0c;是“大規模深度學習模型”的簡稱&#xff0c;指具有大量參數和復雜結構的機器學習模型&#xff0c;可以處理大規模的數據和復雜的問題&#x…

【Java】Queue中增加刪除方法的區別

offer&#xff0c;add 區別&#xff1a; 一些隊列有大小限制&#xff0c;因此如果想在一個滿的隊列中加入一個新項&#xff0c;多出的項就會被拒絕。 這時新的 offer 方法就可以起作用了。它不是對調用 add() 方法拋出一個 unchecked 異常&#xff0c;而只是得到由 offer() 返…

題目:售貨員的難題(狀壓dp)

售貨員的難題 題目描述輸入輸出格式輸入格式&#xff1a;輸出格式&#xff1a; 輸入輸出樣例輸入樣例#1&#xff1a;輸出樣例#1&#xff1a; 思路AC代碼&#xff1a; 題目描述 某鄉有n個村莊( 1 < n < 16 )&#xff0c;有一個售貨員&#xff0c;他要到各個村莊去售貨&am…

consul限制注冊的ip

假設當前服務器的ip是&#xff1a;192.168.56.130 1、允許 所有ip 注冊(驗證可行) consul agent -server -ui -bootstrap-expect1 -data-dir/usr/local/consul -nodedevmaster -advertise192.168.56.130 -bind0.0.0.0 -client0.0.0.0 2、只允許 當前ip 注冊 consul agent -…

Leetcode33 搜索旋轉排序數組

題解&#xff1a; /*** 旋轉排序數組可分為N1 N2兩個部分&#xff0c;如&#xff1a;[4,5,6,7,1,2,3]&#xff0c;N1為[4,5,6,7]&#xff0c;N2為[1,2,3]** 必然滿足以下兩個條件&#xff1a;* 1. N1和N2都是分別遞增的&#xff1b;* 2. N1中的所有元素大于N2中的所有元素;** …

【Python機器學習】實驗12 基于神經網絡的回歸-分類實驗

文章目錄 神經網絡的回歸例1 基于神經網絡的回歸(簡單例子)1.1 導入包1.2 構造數據集&#xff08;隨機構造的&#xff09;1.3 構造訓練集和測試集1.4 構建神經網絡模型1.5 采用訓練數據來訓練神經網絡模型 實驗1 基于神經網絡的分類(鳶尾花數據集)1.1 導入包1.2 構造數據集1.3 …

Selenium瀏覽器自動化測試框架簡單介紹

selenium簡介 介紹   Selenium [1] 是一個用于Web應用程序測試的工具。Selenium測試直接運行在瀏覽器中&#xff0c;就像真正的用戶在操作一樣。支持的瀏覽器包括IE&#xff08;7, 8, 9, 10, 11&#xff09;&#xff0c;Mozilla Firefox&#xff0c;Safari&#xff0c;Googl…