十 数组的方法第二弹
10.1 sort
sort用来对数组进行排序(会对改变原数组)(原地操作)
sort默认会将数组升序排列,这里有一个坑:sort默认会按照Unicode编码进行排序,所以如果直接通过sort对数字进行排序可能会得到一个不正确的结果。
例如:
let arr1 = [1,2,3,150]
arr1.sort()
console.log(arr1); // [1, 150, 2, 3]
相当于转换成字符串,‘1’,‘2’,‘3’,‘150’ 这样
然后从左往右每一位进行对比。
所以sort接收一个函数compareFn(a, b)
作为参数,根据该函数的返回值来进行排序
compareFn(a, b) 返回值 | 排序顺序 |
---|---|
> 0 | a 在 b 后,如 [b, a] |
< 0 | a 在 b 前,如 [a, b] |
=== 0 | 保持 a 和 b 原来的顺序 |
用法举例:
let arr1 = [1,2,3,4,5,6,5,4,100]
arr1.sort((a,b)=>{
return a-b
})
console.log(arr1); // [1, 2, 3, 4, 4, 5, 5, 6, 100]
a-b 如果a大于b,则返回值大于0,交换其位置,就变成了升序排列。
10.2 toSorted
Array
实例的 toSorted()
方法是 sort()
方法的复制方法版本。它返回一个新数组,其元素按升序排列。
所以他和sort()
方法唯一的区别就是sort()
是原地操作,而toSorted()
返回一个新的数组
当我在nodejs16环境下执行以下代码时发生报错 “arr1.toSorted is not a function”
let arr1 = [4,5,1,3,6,9,8,2]
console.log(arr1.toSorted());
原因如下:
At the time of this answer,
Array.prototype.toSorted()
is supported by Node.js version 20+. Most developers use the Node.js LTS version (currently version 18). So if you’re using Node.js version 19, 18 or lower in WebStorm,.toSorted()
is not supported.from—javascript - .toSorted() works only in a browser - Stack Overflow
就是说nodejs 20以上才支持toSorted方法,我的nodejs16不支持,和之前遇到的structuredClone()方法一样。
10.3 forEach
forEach()
方法对数组的每个元素执行一次给定的函数。执行函数的必选参数,后面还有一个可选参数thisArg
,用于执行 callbackFn
时用作 this
的值。
简单用法示例:
let arr = [1,2,3,4,5]
arr.forEach((x)=>{console.log(x**2);})
执行函数可以接收三个值:
-
element 当前的元素
-
index 当前元素的索引
-
array 被遍历的数组
let arr = [1,2,3,4,5]
arr.forEach((element,index,array)=>{
console.log("当前元素:"+element);
console.log("元素下标:"+index);
console.log("原数组:"+array);
console.log("--------------------");
})
当使用箭头函数时,thisArg
参数会失效,因为因为箭头函数在词法上绑定了this
值。
let arr = [1,2,3,4,5]
arr.forEach((element,index,array)=>{
console.log(this);
},{"user":"大眼神龙"})
/*
{}
{}
{}
{}
{}
*/
我们来使用普通函数验证一下:
let arr = [1,2,3,4,5]
arr.forEach(function(x){console.log(this);},{"user":"大眼神龙"})
/*
{user: '大眼神龙'}
{user: '大眼神龙'}
{user: '大眼神龙'}
{user: '大眼神龙'}
{user: '大眼神龙'}
*/
10.4 filter
filter()
方法创建给定数组一部分的浅拷贝的新数组,其包含通过所提供函数实现的测试的所有元素。
- 非破坏性方法,不会影响原数组
实例如下:
let arr = [1,2,2,3,4,5,6]
let res = arr.filter((x)=>{return x**2 === 4})
console.log(res); // [2,2]
实现了获取原数组中平方等于4的所有元素浅拷贝后的新数组。
接收一个回调函数作为参数,该回调函数可以接收三个值(同forEach)
- element:数组中当前正在处理的元素。
- index:正在处理的元素在数组中的索引。
- array:调用了
filter()
的数组本身。
同时也可以接收一个thisArg方法用作执行 callbackFn
时 this
的值(同forEach)
10.5 map
map()
方法创建一个新数组,这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成。
示例如下:
let arr = [1,2,2,3,4,5,6]
let res = arr.map((x)=>{return x**2})
console.log(res); // [1, 4, 4, 9, 16, 25, 36]
map有“映射”的意思,新数组与原数组之间是一一映射的关系
接收一个回调函数作为参数,该回调函数可以接收三个值(同filter、forEach)
- element:数组中当前正在处理的元素。
- index:正在处理的元素在数组中的索引。
- array:调用了
filter()
的数组本身。
同时也可以接收一个thisArg方法用作执行 callbackFn
时 this
的值(同filter、forEach)
10.6 reduce
reduce()
方法对数组中的每个元素按序执行一个提供的 reducer 函数,每一次运行 reducer 会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值。
感觉没什么用处,还不太好理解,感觉就和滚雪球一样,应该在一些特殊的应用场景下需要。
语法:
reduce(callbackFn)
reduce(callbackFn, initialValue)
接收一个函数callbackFn
,其返回值作为计算结果;
接收一个可选参数initialValue
,其将作为初始值(第一个计算结果),如果不传该参数则默认初始值为array[0]
的值
callbackFn
函数又可接收四个参数:
- accumulator:上一次调用
callbackFn
的返回值。在第一次调用时,如果指定了initialValue
则为指定的值,否则为array[0]
的值。 - currentValue:当前值
- currentIndex:当前索引
- array:数组本身
例如计算数组所有元素的和:
let arr = [1,2,3,4,5,6]
let res = arr.reduce((a,b)=>{return a+b})
console.log(res); // 21
当提供初始值时,就是数组总和+初始值:
let arr = [1,2,3,4,5,6]
let res = arr.reduce((a,b)=>{return a+b},100)
console.log(res); // 121