关于数组的一些笔记
2018年02月18日 数组的复制
数组是复合的数据类型,直接复制的话,只是复制了指向底层数据结构的指针,而不是克隆一个全新的数组。
var a1 = [1,2,3];
var a2 = a1;
a2[0] = 3;
console.log(a1);
// 打印出-> [3,2,3]
如上,复制后改变a2的数据,a1也会跟着改变。因为只是复制了指向数据的指针,实际a1和a2在内存中是同一个数据。
解决方法
- ES5方法 -> 利用Array的concat()方法
concat() 方法用于连接数组。 该方法不会改变现有的数组,而仅仅会 返回被连接数组的一个副本。
var a1 = [1,2,3];
var a2 = a1.concat();
a2[0] = 3;
console.log(a1);
// 打印出-> [1,2,3]
- ES6方法 -> 利用扩展运算符(…)
扩展运算符以三个点的形式出现 … 可以将数组或者对象里面的值展开。const a1 = [1, 2,3]; const a2 = [...a1];
数组的合并
扩展运算符提供了数组合并的新写法。
const arr1 = ['a', 'b'];
const arr2 = ['c'];
const arr3 = ['d', 'e'];
// ES5 的合并数组
arr1.concat(arr2, arr3);
console.log(arr1);
// [ 'a', 'b', 'c', 'd', 'e' ]
// ES6 的合并数组
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]
不过,这两种方法都是浅拷贝,使用的时候需要注意。
const a1 = [{ foo: 1 }];
const a2 = [{ bar: 2 }];
const a3 = a1.concat(a2);
const a4 = [...a1, ...a2];
a3[0] === a1[0] // true
a4[0] === a1[0] // true
上面代码中,a3和a4是用两种不同方法合并而成的新数组,但是它们的成员都是对原数组成员的引用,这就是浅拷贝。如果修改了原数组的成员,会同步反映到新数组。
利用ES6的set数据结构进行数组去重
ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
[...new Set(array)];
// 或者
Array.from(new Set(array));
利用ES6数组的flat()方法将多维数组转为一维数组
数组的成员有时还是数组,Array.prototype.flat()用于将嵌套的数组“拉平”,变成一维的数组。该方法返回一个新数组,对原数据没有影响。
[1, 2, [3, 4]].flat()
// [1, 2, 3, 4]
上面代码中,原数组的成员里面有一个数组,flat()方法将子数组的成员取出来,添加在原来的位置。
flat()默认只会“拉平”一层,如果想要“拉平”多层的嵌套数组,可以将flat()方法的参数写成一个整数,表示想要拉平的层数,默认为1。
[1, 2, [3, [4, 5]]].flat()
// [1, 2, 3, [4, 5]]
[1, 2, [3, [4, 5]]].flat(2)
// [1, 2, 3, 4, 5]
上面代码中,flat()的参数为2,表示要“拉平”两层的嵌套数组。
如果不管有多少层嵌套,都要转成一维数组,可以用Infinity关键字作为参数。
[1, [2, [3]]].flat(Infinity)
// [1, 2, 3]
如果原数组有空位,flat()方法会跳过空位。
[1, 2, , 4, 5].flat()
// [1, 2, 4, 5]