一: 创建数组
1. 数组字面量
js
let a = []
var b = [1, 'a', true]
注意: 还有一个稀疏数组,反正我没用过,工作中也很少见人用,大多数规范都不让用稀疏数组
2. 对可迭代对象使用...扩展操作符(ES6)
2.1 可迭代对象
- 可迭代对象是指可以用for/of循环遍历的对象,如数组、字符串,集合和映射等
2.2 ...扩展操作符
- ES2018以后,...扩展操作符在对象字面量也可以使用了
- 出现在等号右边或参数位置的
...
通常是展开(拆开)。 - 出现在等号左边或参数声明的
...
通常是剩余(收集)。
2.3 扩展操作符是创建数组(浅)副本的一种便携方式:(浅拷贝)
js
let originalArr = [1,2,3];
let copyArr = [...origonalArr];
copyArr[0] = 0; // 修改copyArr不会影响originalArr
originalArr[0] // => 1
const original = { hobbies: ['reading', 'swimming'] };
const copy = { ...original }; // 浅拷贝
// 修改嵌套数组中的元素(修改第二层)
copy.hobbies[0] = 'gaming';
console.log(original.hobbies); // 输出: ['gaming', 'swimming'] (被影响了!)
console.log(copy.hobbies); // 输出: ['gaming', 'swimming']
3. Array()构造函数
3.1 不传参调用
- let a = new Array(); 这样会创建一个没有元素的空数组,等价于字面量[]
3.2 传入一个数组参数,指定长度:
- let a = new Array(10);
- 这样会创建一个指定长度的数组。
- 如果提前知道需要多少个数组元素,可以这样做来预先为数组分配空间
注意:
这时的数组中不会存储任何值,数组索引属性"0", "1"等甚至都没有定义
3.3 传入两个或更多个数组元素,或传入一个非数值元素
- 这样调用的话,构造函数的参数会成为新数组的元素。使用数组字面量永远比这种方法简单。
js
// [5, 4, 3, 2, 1, 'testing, testing']
let a = new Array(5, 4, 3, 2, 1, "testing, testing")
// ['sddsdsdsd']
let b = new Array('sddsdsdsd')
3.4 工厂方法Array.of()和Array.from()
-
Array.of()
-
解决了Array()在使用数值参数时,如果只有一个参数,这个参数指定的是数组的长度,多个又变成了数组元素
-
Array.of(),可以使其参数值(无论多少个)多为数组的元素来创建并返回新数组
jsArray.of([1,2,3]); // [[1,2,3]] Array.of(3); // [3]
-
-
Array.from()
- 这个方法就是将一个类数组对象或者一个可迭代对象转换成新数组,如果传入的是可迭代对象,那他就和使用...扩展操作符操作一样
- Array.from()定义了一种给类数组对象创建真正的数组副本的机制
二、数组的增删改查
1. 读写
-
\]操作符中间包裹一个索引
2. 数组的长度
- 每个数组都有length属性,正是这个属性让数组有别于常规的JavaScript对象,对于非稀疏数组,length属性就是数组中元素的个数。这个值比数组的最高索引大1
3. 增删
3.1 添加
- 使用一个新索引赋值:例如:arr[arr.length] = 0
- push(): 等同于arr[arr.length],末尾追加
- unshift(): 从开头追加
3.2 删除
- 可以使用delete操作符
js
let a = [1,2,3];
delete a[2]; // 现在索引2没有元素了
2 in a; // => false: 数组索引2没有定义
a.length; // => 3: 删除元素不影响数组长度
- 把数组length设置成一个新长度值,也可以从末尾删除元素
- splice()是一个可以插入,删除或替换数组元素的通用方法
- pop()删除最后的元素,并返回删除值
- shift()删除第一个元素,并返回删除值
三、数组的方法
1 迭代方法(循环)
简介
首先,所有这些方法都接收一个函数作为第一个参数
,并且对数组的每一个元素(或某些元素)都调用一次这个函数。如果数组是稀疏的,则不会对不存在的元素调用传入这个函数。多数情况下,我们提供的这个函数被调用时都会接收到3个参数
,分别是数组元素的值
、数组元素的索引
和数组本身
。通常
我们只需要
这几个参数中的第一个
,可以忽略第二和第三个值。
多数迭代器方法
都接收可选的第二个参数
。如果指定这个参数,则第一个函数在被调用时就好像它是第二个参数的方法一样。换句话说,我们传入的第二个参数会成为作为第一个参数传入的函数内部的this值
。传入函数的返回值通常不重要,但不同的方法会以不同的方式处理这个返回值。本节介绍的所有方法都不会修改调用它们的数组。(当然,传入的函数可能会修改这个数组)
forEach()
注意:forEach()并未提供一种提前终止迭代的方式。换句话说,在这里没有常规for循环中的break语句对等的机制。
map()
- map()方法把调用它的数组的每个元素分别传给我们指定的函数,返回这个函数的返回值构成的数组。
- 对于map()方法来说,我们传入的函数应该有返回值
- 注意:map()返回一个新数组,并不修改原数组
- 如果数组是稀疏的,则缺失的元素不会调用我们的函数,但返回的数组也会与原始数组一样稀疏:长度相同,缺失的元素也相同。
filter()
- filter()方法返回一个数组,该数组包含调用它的数组的子数组
- 传给这个方法的函数应该是
断言函数
,即返回true或false的函数
。这个函数与传给forEach()和map()的函数一样被调用。如果函数返回true或返回值能转换为true,则传给这个函数的的元素就是filter最终返回的子数组的成员
- 注意:filter()会跳过稀疏数组中缺失的元素,它返回的数组始终是稠密的。因此可以使用该方法清掉稀疏数组中的空隙
- 用自己的话来说,这就是一个过滤函数,返回一个包含满足条件元素的数组
find()与findIndex()
- find(),在找到满足条件的第一个元素时停止迭代,返回匹配的值;找不到满足条件的元素,返回undefined。
- findIndex(),在找到满足条件的第一个元素时停止迭代,返回匹配的值的索引;找不到满足条件的元素,返回-1。
every()与some()
- every(),类似数学上的"全称"量词∀类似,它在且只在所有元素都满足断言函数的时候,才返回true
- some(),类似数学上的"存在"量词∃类似,它是只要有一个元素满足断言函数的时候,就返回true,但必须所有元素都不满足的时候才返回false
- 注意: some()遇到第一个返回true的就会停止迭代。同样,every()遇到第一个返回false的也会停止迭代。
- 注意: 如果空数组调用它们,every()返回true,some()返回false
reduce()与reduceRight()
-
reduce()和reduceRight()方法使用我们指定的函数归并数组元素,最终产生一个值。
-
reduce()接收两个参数。第一个是执行归并的函数。第二个参数是可选的,是传给归并函数的初始值。
-
在reduce()中使用的函数与在forEach()和map()中使用的函数不一样。我们熟悉的值、索引和数组本身在这里作为第二、第三和第四参数。第一个参数是目前为止归并操作的累积结果。
-
如果reduce()调用时未传第二个参数,那么数组的第一个元素会被作为初始值
-
如果不传初始值,在空数组上调用reduce()会导致TypeError。如果调用它时只有一个值,或者用空数组调用但传了初始值,则reduce直接返回这个值,不会调用归并函数
-
reduceRight()与reduce()类似,只不过从高索引向低索引(从右向左)处理数组,而不是从低向高。如果归并操作具有从右到左的结合性,那可能要考虑使用reduceRight(), 比如:
js// 计算2^(3^4)。求幂具有从右到左的优先级 let a = [2, 3, 4] a.reduceRight((acc, val) => Math.pow(val, acc))
-
注意: 无论reduce()还是reduceRight()都不接收用于指定归并函数this值的可选参数。它们用可选的初始值参数取代了这个值。如果需要可以考虑bind()方法
2. 使用flat()和flatMap()打平数组
-
flat()只能打平一级
js[1, 2, [3, 4, [5]]].flat() // =>[1, 2, 3, 4, [5]]
-
flatMap()方法与map()方法类似,只不过返回的数组会自动被打平,就像传给了flat()一样。换句话说,调用a.flatMap(f)等同于(但效率远高于)a.map(f).flat()