數組扁平化處理

今天看到一篇文章,其中講解了數組扁平化處理的多種方法,個人覺得還是有點意思,現詳細講解幾種實現的方法。

  1. 使用forEach
	function  flatten1(arr){
		let res = [];
		arr.forEach((val)=>{				
			res.push( ...( Array.isArray(val) ? flatten1(val) : [val] ) );
		});
		return res;
	}

這個方法沒啥好說的,運用了遞歸,同時使用了...操作符將數組進行了展開

  1. 使用reduce
	function  flatten2(arr){			
		return arr.reduce((prev, curr)=>{				
			return prev.concat( Array.isArray(curr) ? flatten2(curr) :  curr  );			
		}, [] );
	}

這個方法也很好理解,就是使用reduce的特性,同時使用了遞歸

  1. 使用some
	function  flatten3(arr){
		while( arr.some( val=>Array.isArray(val) ) ){
			arr = [].concat(...arr);
		}
		return arr;
	}

該方法雖然沒有前面幾種方法實現的n那麼優雅,但是還是給了我一些驚喜。因爲猛一看,我竟然沒發現實現的具體原理。
直到我輸入了下面的測試代碼,我才明白:

	var a = [].concat(1,2, [3,4]);
	var b = [].concat(1,2,[ [5, 6] , 7 ]);
	console.log(a); //[1, 2, 3, 4]
	console.log(b) ;//[1, 2, Array(2), 7]

也就是說concat中跟隨的項可以包含一維數組,而且一維數組會被展開,但二維數組就不可以。這和我預期的還是不一樣的。所以還是基礎知識不夠牢靠啊!

後來查閱了一下MDN,發現這麼一個注意

數字和布爾(不是String,Number 和 Boolean 對象):concat將字符串和數字的值複製到新數組中。
注意:數組/值在連接時保持不變。此外,對於新數組的任何操作(僅當元素不是對象引用時)都不會對原始數組產生影響,反之亦然。

也就是說concat對於對象的拷貝是淺拷貝,舉個列子:

	var a = [{a:1}, 2], b = [];
	var c = a.concat(b);
	
	c[0].a = 3;
	console.log( a[0].a ); //3

可以看到我們在鏈接後的新對象c中更改了數組中的第一項的屬性a的值,結果這個更改在數組a的第一項也發生了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章