for、for-in、for-of、forEach的區別


總結

for..of適用遍歷數/數組對象/字符串/map/set等擁有迭代器對象的集合.但是不能遍歷對象,因為沒有迭代器對象.與forEach()不同的是,它可以正確響應break、continue和return語句。

for-of循環不支持普通對象,但如果你想迭代一個對象的屬性,你可以用for-in循環(這也是它的本職工作)或內建的Object.keys()方法。

for in遍歷的是數組的索引(即鍵名),而for of遍歷的是數組元素值。for of遍歷的只是數組內的元素,而不包括數組的原型屬性method和索引name。

forEach(value,index,Array)不能同時遍歷多個集合,在遍歷的時候無法修改和刪除集合數據,方法不能使用break,continue語句跳出循環,或者使用return從函數體返回,對於空數組不會執行回調函數。

forEach與for當循環遍歷為空的數組時,forEach會跳過為空的值,for不會跳過為空的數據,會直接顯示undefined。兩者都能識別出NULL。

forEach() 被調用時,不會改變原數組,也就是調用它的數組(盡管 callback 函數在被調用時可能會改變原數組)。


具體區別如下:

FOR

var arrList = [1,2,3,4,5,6]
for(var i = 0;i < arrList.length ; i++){
    console.log(arrList[i]);
}

FOR-IN

語法

for (variable in object)
  statement
  • variable

    在每次迭代時,variable會被賦值為不同的屬性名。

  • object

    非Symbol類型的可枚舉屬性被迭代的對象。

描述

for...in 循環只遍歷可枚舉屬性(包括它的原型鏈上的可枚舉屬性)。ArrayObject使用內置構造函數所創建的對象都會繼承自Object.prototypeString.prototype的不可枚舉屬性,例如 StringindexOf() 方法或 ObjecttoString()方法。循環將遍歷對象本身的所有可枚舉屬性,以及對象從其構造函數原型中繼承的屬性(更接近原型鏈中對象的屬性覆蓋原型屬性)。

舉例

/*
	FOR..IN語句遍歷數組
*/
Array.prototype.method=function(){
  console.log(this.length);
}
var myArray=[1,2,4]
myArray.name="數組"
for (var index in myArray) {
  console.log(myArray[index]);
}
/*
	輸出結果順序不唯一。輸出的結果包含如下:
	1 
	2 
	4 
	數組
	ƒ (){
  	console.log(this.length);
	}
*/
/*
	FOR..IN語句遍歷對象
*/
Object.prototype.method=function(){
  console.log(this);
}
var myObject={
  a:1,
  b:2,
  c:3
}
for (var key in myObject) {
  console.log(key);
}
/*
	輸出結果順序不唯一。輸出的結果包含如下:
	a 
	b
	c 
	method
	
	1- for in 可以遍歷到myObject的原型方法method,如果不想遍歷原型方法和屬性的話,可以在循環內部判斷一		下,hasOwnPropery方法可以判斷某屬性是否是該對象的實例屬性.
	2- 通過ES5的Object.keys(myObject)獲取對象的實例屬性組成的數組,不包括原型方法和屬性.
*/

for (var key in myObject) {
  if(myObject.hasOwnProperty(key)){
    console.log(key);
  }
}
/*
	輸出結果順序不唯一。輸出的結果包含如下:
	a 
	b
	c 
*/

注意事項

  • FOR..IN語句遍歷的是索引index(鍵名)為字符串型數字,不能直接進行幾何運算。

  • 遍歷順序有可能不是按照實際數組的內部順序。FOR..IN語句以任意順序遍歷一個對象的除Symbol以外的可枚舉屬性。

  • 使用for in會遍歷數組所有的可枚舉屬性,包括原型。例如上述案例的原型方法method和name屬性,所以for in更適合遍歷對象,不要使用for in遍歷數組。

刪除,添加或者修改屬性

for...in 循環以任意序迭代一個對象的屬性(請參閱delete運算符,了解為什么不能依賴於迭代的表面有序性,至少在跨瀏覽器設置中)。如果一個屬性在一次迭代中被修改,在稍后被訪問,其在循環中的值是其在稍后時間的值。一個在被訪問之前已經被刪除的屬性將不會在之后被訪問。在迭代進行時被添加到對象的屬性,可能在之后的迭代被訪問,也可能被忽略。

通常,在迭代過程中最好不要在對象上進行添加、修改或者刪除屬性的操作,除非是對當前正在被訪問的屬性。這里並不保證是否一個被添加的屬性在迭代過程中會被訪問到,不保證一個修改后的屬性(除非是正在被訪問的)會在修改前或者修改后被訪問,不保證一個被刪除的屬性將會在它被刪除之前被訪問。

FOR-OF

for...of語句可迭代對象(包括 ArrayMapSetStringTypedArrayarguments 對象等等)上創建一個迭代循環,調用自定義迭代鈎子,並為每個不同屬性的值執行語句。不建議遍歷原有的原生對象。

語法

for (variable of iterable) {
    //statements
}
  • variable

    在每次迭代中,將不同屬性的值分配給變量。

  • iterable

    被迭代枚舉其屬性的對象。

示例

/*
	FOR..OF語句遍歷數組
*/
var myArray=[1,2,4,5,6,7,8]
for (var index of myArray) {
  console.log(index);
}
/*
	輸出結果順序唯一。輸出的結果如下:
	1
	2
	4
	5
	6
	7
	8
*/

FOREACH

語法

arr.forEach(callback(currentValue [, index [, array]])[, thisArg]);

參數

  • callback

    為數組中每個元素執行的函數,該函數接收三個參數:currentValue數組中正在處理的當前元素。index 可選數組中正在處理的當前元素的索引。array 可選forEach() 方法正在操作的數組。

  • thisArg 可選

    可選參數。當執行回調函數 callback 時,用作 this 的值。

返回值

undefined

描述

forEach() 方法按升序為數組中含有效值的每一項執行一次 callback 函數,那些已刪除或者未初始化的項將被跳過(例如在稀疏數組上)。

舉例

/*
	數組中未定義或者undefined數據的情況。
*/
const arraySparse = [1,3,,7];
let forCallbackRuns = 0;
let forEachCallbackRuns = 0;

arraySparse.forEach(function(element){
  console.log(element);
  forEachCallbackRuns++;
});

console.log("forEachCallbackRuns: ", forEachCallbackRuns);

/*
1
3
7
numCallbackRuns: 3
*/


for(var i = 0; i < arraySparse.length ; i++){
  console.log(arraySparse[i]);
  forCallbackRuns++;
}
console.log("forCallbackRuns: ", forCallbackRuns);

/*
1
3
undefined
7
forCallbackRuns:  4
*/

/*
	數組中含有null數據的情況。
*/
const arraySparse = [1,3,null,7];
let forCallbackRuns = 0;
let forEachCallbackRuns = 0;

arraySparse.forEach(function(element){
  console.log(element);
  forEachCallbackRuns++;
});

console.log("forEachCallbackRuns: ", forEachCallbackRuns);

/*
1
3
null
7
forEachCallbackRuns:  4
*/


for(var i = 0; i < arraySparse.length ; i++){
  console.log(arraySparse[i]);
  forCallbackRuns++;
}
console.log("forCallbackRuns: ", forCallbackRuns);

/*
1
3
null
7
forCallbackRuns:  4
*/

注意

除了拋出異常以外,沒有辦法中止或跳出 forEach() 循環。如果你需要中止或跳出循環,forEach() 方法不是應當使用的工具。

若你需要提前終止循環,你可以使用:

這些數組方法則可以對數組元素判斷,以便確定是否需要繼續遍歷:

譯者注:只要條件允許,也可以使用 filter() 提前過濾出需要遍歷的部分,再用 forEach() 處理。

參考資料鏈接

作者:Haiya_32ef 鏈接:https://www.jianshu.com/p/c43f418d6bf0

作者:weixin_34128411 鏈接:https://blog.csdn.net/weixin_34128411/article/details/94279246


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM