数组的新增和扩展
扩展运算符
const arr = [1, 2, 3]
console.log(...arr) // 1 2 3
// 与函数的 rest 参数一致
// 替代了 apply
运用
- 复制数组
const arr = [1, 2]
const copyArr = [...arr]
// 或
const [...copyArr] = arr
- 合并数组
// ES6以前
const arr = arr1.concat(arr2, arr3)
// ES6
const arr = [...arr1, ...arr2, ...arr3]
- 解构赋值结合
const [first, ...rest] = [1, 2, 3]
first // 1
rest // [ 2 , 3 ]
- Iterator 接口
部署了 Iterator 接口的数据类型,都能使用扩展运算符。(知识点延伸:也都能用 for...of 遍历) 甚至可以自定义一个 Iterator 接口,然后自定义返回值
部署了 iterator 接口的数据解构:
- Array
- Map
- Set
- String
- TypedArray
- 函数的 arguments 对象
- NodeList 对象
例:
// 字符串
[...'str'] // [ s, t, r ]
- Generator 函数
const go = function* () {
yield 1
yield 2
yield 3
}
[...go()] // [1, 2, 3]
构造函数方法
Array.from()
将两类对象转化为数组(类似数组的对象、可遍历的对象)
let arrayLike = {
0: 'a',
1: 'b',
2: 'c',
length: 3,
}
// ES5 的写法
var arr1 = [].slice.call(arrayLike) // ['a', 'b', 'c']
// ES6 的写法
let arr2 = Array.from(arrayLike) // ['a', 'b', 'c']
场景延伸
// 转换 DOM 元素集合为数组
const buttons = document.querySelectorAll('button')
const buttonArray = Array.from(buttons)
// 处理函数的 arguments 对象
function sum() {
const args = Array.from(arguments)
}
// 生成 [0, 1, 2, 3, 4]
const numbers = Array.from({ length: 5 }, (_, index) => index)
// 转换Set为数组(去重常用)
const set = new Set([1, 2, 2, 3])
const uniqueArray = Array.from(set)
console.log(uniqueArray) // [1,2,3]
// 转换字符串为字符数组
const str = 'hello'
const charArray = Array.from(str)
console.log(charArray) // ['h','e','l','l','o']
Array.of()
将一组值转化为数组
Array.of(3, 11, 8) // [ 3, 11, 8]
场景延伸
// 封装一个创建数组的函数
function createArray(...args) {
// 无论传入几个参数,都返回包含这些参数的数组
return Array.of(...args)
}
console.log(createArray('a', 'b')) // ['a','b']
console.log(createArray(null, undefined)) // [null, undefined]
// 比如处理API返回的零散数据,组装成数组
const userId = 1001
const userName = '李四'
const userAge = 25
// 语义化:“用这些参数创建一个用户信息数组”
const userInfo = Array.of(userId, userName, userAge)
console.log(userInfo) // [1001, '李四', 25]
实例方法
copyWithin()
复制数组的一部分,去覆盖另一部分。会改变原数组
// 被覆盖起始点,复制的起始点,复制结束点(不包含)
[1, 2, 3, 4, 5].copyWithin(0, 2, 4)
// [ 3, 4, 3, 4, 5 ]
find()、findIndex()、fandLast()、findLastIndex()
// 从前往后找
[1, 4, 5, 10].find((n) => n > 0) // 1
[1, 4, 5, 10].findIndex((n) => n > 0) // 0
// 从后往前找
[1, 4, 5, 10].findLast((n) => n > 0) // 10
[1, 4, 5, 10].findLast((n) => n > 0) // 3
fill()
// 用一个值填充数组,会改变原数组
[1, 2, 3].fill(7) // [ 7, 7, 7 ]
entries()、keys()、values()
// 遍历键值对
for (let [index, item] of ['a', 'b'].entries()) {
console.log(index, item)
}
// 0 a
// 1 b
// 遍历键名
for (let index of ['a', 'b'].keys()) {
console.log(index)
}
// 0
// 1
// 遍历键值
for (let item of ['a', 'b'].values()) {
console.log(item)
}
// a
// b
includes()
[1, 2].includes(2) // true
flat()、flatMap()
数组扁平化。返回新数组
const arr1 = [1, [2, [3]]]
// 默认拉平一层,可以设置层数或 Infinity 关键字
arr1.flat() // [ 1, 2, [ 3 ]]
arr1.flat(2) // [ 1, 2, 3 ]
const arr2 = [[1, [2]]]
// 只能拉平一层,额外增加 map 方法的功能
arr2.flatMap((item) => item * 2)
at()
// 负数索引
['a', 'b'].at(-1) // b
// 也可用于字符串
'str'.at(-1) // r
toReversed(),toSorted(),toSpliced(),with()
// 都是为了不改变原数组
const arr = [1, 2, 3]
arr.toReversed() // [3, 2, 1]
arr // [1, 2, 3]
const arr = [3, 1, 2]
arr.toSorted() // [1, 2, 3]
arr // [3, 1, 2]
const array = [1, 2, 3, 4]
array.toSpliced(1, 2, 5, 6, 7) // [1, 5, 6, 7, 4]
array // [1, 2, 3, 4]
const correctionNeeded = [1, 1, 3]
correctionNeeded.with(1, 2) // 只删除一个: [1, 2, 3]
correctionNeeded // [1, 1, 3]
group()、groupToMap()(ES2024)
数组内容分组。方法较新(ES2024),注意兼容
// 按照字符串分组就使用 group(),按照对象分组就使用 groupToMap()
const array = [1, 2, 3, 4, 5]
array.group((num, index, array) => {
return num % 2 === 0 ? 'even' : 'odd'
})
// { odd: [1, 3, 5], even: [2, 4] }
const array = [1, 2, 3, 4, 5]
const odd = { odd: true }
const even = { even: true }
array.groupToMap((num, index, array) => {
return num % 2 === 0 ? even : odd
})
// Map { {odd: true}: [1, 3, 5], {even: true}: [2, 4] }
数组的空位
由于空位的处理规则非常不统一,所以建议避免出现空位
es6.ruanyifeng.com/#docs/array…
Array.prototype.sort() 的排序稳定性
现在 JavaScript 各个主要实现的默认排序算法都是稳定的