关注前端小讴,阅读更多原创技术文章
Array
- ECMAScript 的数组是一组有序的数据(和其他语言相同),每个槽位可以存储任意类型的数据(和其他语言不同)
- ECMAScript 的数组是动态大小的,随着数据添加而自动增长
相关代码→
创建数组
-
使用 Array 构造函数
let colors = new Array()
console.log(colors) // []
- 给构造函数传入一个参数:若参数是数值,则 length 属性会被自动创建并设置为这个值;若参数不是数值,则创建只包含该参数的数组
colors = new Array(10)
console.log(colors) // [ `<10 empty items>` ]
colors = new Array(true)
console.log(colors) // [ true ]
- 给构造函数传入多个参数,会自动创建包含这些参数的数组
colors = new Array('red', 'blue')
console.log(colors) // [ 'red', 'blue' ]
colors = Array(5)
console.log(colors) // [ `<5 empty items>` ]
-
使用数组字面量表示法(同对象字面量表示法,使用数组字面量表示法创建数组时,不会调用 Array 构造函数)
colors = ['red', 'blue', 3]
colors = []
-
ES6 新增 Array.from()
,将类数组结构转换为数组实例
- 第一个参数是一个类数组对象,即任何可迭代结构或者包含 length 属性和可索引元素的结构
console.log(Array.from('Matt')) // [ 'M', 'a', 't', 't' ],字符串被拆分为单字符数组
console.log(Array.from(new Map().set(1, 2).set(3, 4))) // [ [ 1, 2 ], [ 3, 4 ] ],集合和映射转换为数组
console.log(Array.from(new Set().add(1).add(2).add(3).add(4))) // [ 1, 2, 3, 4 ],集合和映射转换为数组
const a1 = [1, 2, 3, 4]
const a2 = Array.from(a1) // 浅拷贝,a2与a1引用不同的基对象
console.log(a2) // [ 1, 2, 3, 4 ]
console.log(a1 === a2) // false
const a3 = a1 // a3与a1引用同一个基对象
console.log(a1 === a3) // true
const iter = {
*[Symbol.iterator]() {
yield 1
yield 2
yield 3
yield 4
},
}
console.log(Array.from(iter)) // [ 1, 2, 3, 4 ],可迭代对象转换为数组
function getColors() {
console.log(Array.prototype.slice.call(arguments)) // [ 'red', 'blue' ],将argumens对象转换为数组
console.log(Array.from(arguments)) // [ 'red', 'blue' ],将argumens对象转换为数组
}
getColors('red', 'blue')
const arrayLikeObject = {
0: 1,
1: 2,
2: 3,
3: 4,
length: 4,
}
console.log(Array.from(arrayLikeObject)) // [ 1, 2, 3, 4 ],带有必要属性的自定义对象转换为数组
- 第二个可选参数是一个映射函数,可直接增强新数组的值
const a4 = Array.from(
a1,
(x) => x + 2 // 第二个可选参数:映射函数,增强数组
) // 增强新数组a4的值
console.log(a4) // [ 3, 4, 5, 6 ]
- 第三个可选参数是一个对象,用于指定映射函数中 this 的值,此时映射函数不要用箭头函数
const a5 = Array.from(
a1,
function (x) {
console.log(this) // { exponent: 2 },第三个参数中指定this的值,此时不可用箭头函数
return x ** this.exponent
},
{ exponent: 2 } // 第三个可选参数:指定映射函数中this的值
)
console.log(a5) // [ 1, 4, 9, 16 ]
const a6 = Array.from(a1, (x) => x ** this.exponent, { exponent: 2 }) // 如使用箭头函数
console.log(a6) // [ NaN, NaN, NaN, NaN ]
const a7 = Array.from(a1, (x) => this, { exponent: 2 }) // 因为用箭头函数,this的值是空对象
console.log(a7) // [ {}, {}, {}, {} ]
-
ES6 新增Array.of()
,将一组参数转换为数组
console.log(Array.of(1, 2, 3, 4)) // [ 1, 2, 3, 4 ],将参数转换为数组
console.log(Array.of(undefined, null)) // [ undefined, null ],将参数转换为数组
创建数组 |
语法 |
参数 |
构造函数 |
let arr = new Array(3) |
单个数值/单个非数值/多个 |
数组字面量 |
let arr = ['red','blue'] |
|
Array.from() |
Array.from('Matt') |
① 类数组对象 ② 映射函数 ③ 指定映射函数 this 值的对象 |
Array.of() |
Array.of(1, 2, 3, 4) |
一组参数 |
数组空位
- 使用数组字面量初始化数组时,可以使用一串逗号来创建空位
let options = [, , , , ,] // 创建包含5个元素的数组
console.log(options.length) // 5
console.log(options) // [ `<5 empty items>` ]
- 与之前的版本不同,ES6 新增的方法普遍将这些空位当成 undefined 元素
options = [1, , , , 5]
console.log(options) // [ 1, `<3 empty items>`, 5 ]
// es6的for-of语句
for (const option of options) {
console.log(option === undefined)
/*
false
true
true
true
false
*/
}
// es6的for-of语句+entries()方法
for (const [index, value] of options.entries()) {
console.log(value)
/*
1
undefined
undefined
undefined
5
*/
}
console.log([, , ,]) // [ `<3 empty items>` ]
// es6的Array.from()方法
console.log(Array.from([, , ,])) // [ undefined, undefined, undefined ]
// es6的Array.of()方法
console.log(Array.of(...[, , ,])) // [(undefined, undefined, undefined)]
- ES6 之前的方法会忽略这个空位,但具体行为也因方法而已
console.log(options.map(() => 6)) // [ 6, `<3 empty items>`, 6 ],map会跳过空位置
console.log(options.join('-')) // '1----5',join视空位置为空字符串
- 由于行为不一致且存在性能隐患,实践中尽量避免使用数组空位,如确实需要,可以显示地用 undefined 代替
数组索引
- 使用中括号并提供相应值的数字索引,可取得或设置数组的值
- 索引小于数组包含的元素数,则返回存储在相应位置的元素
- 索引大于等于包含的元素书,则数组长度自动扩展到该索引值加 1(若中间还有元素,则自动用 undefined 填充)
colors = ['red', 'blue', 'green']
console.log(colors[0]) // 'red',数组第1项
colors[2] = 'black' // 设置数组第3项,重设数组原有的值
console.log(colors) // [ 'red', 'blue', 'black' ]
colors[3] = 'brown' // 设置数组第4项,扩展数组
console.log(colors) // [ 'red', 'blue', 'black', 'brown' ]
- 数组中元素的数量保存在
length
属性中,始终返回 0 或大于 0 的值
console.log(colors.length) // 4,数组的长度是4
- 通过修改数组的
length
属性,可以从数组末尾删除或添加元素
- 将
length
值设置为小于数组元素数的值,则只保留数组前length
位元素,剩余的末尾元素将被删除
- 将
length
值设置为大于数组元素数的值,则新添加的元素都将以undefined
填充
colors.length = 3 // 将数组的长度设置为3,自动删除末尾'brown'
console.log(colors[3]) // undefined
colors.length = 5 // 将数组长度设置为5,新添加的元素以undefined填充
console.log(colors[5]) // undefined
colors = ['red', 'blue', 'green']
colors[colors.length] = 'black' // 向数组末尾添加'black'
colors[colors.length] = 'brown' // 向数组末尾添加'brown'
console.log(colors) // [ 'red', 'blue', 'green', 'black', 'brown' ]
检测数组
检测数组 |
适用情况 |
instanceof |
只有一个全局作用域(只有一个网页/没有额外的 iframe) |
Array.isArray() |
任何时候(不用考虑在哪个全局上下文),首选 |
迭代器方法
- ES6 在 Array 原型上暴露了 3 个检索数组内容的方法:
keys()
、values()
、entries()
keys()
返回数组索引的迭代器
values()
返回数组元素的迭代器
entries()
返回索引/值对的迭代器
colors = ['red', 'blue', 'green']
console.log(Array.from(colors.keys())) // [ 0, 1, 2 ]
console.log(Array.from(colors.values())) // [ 'red', 'blue', 'green' ]
console.log(Array.from(colors.entries())) // [ [ 0, 'red' ], [ 1, 'blue' ], [ 2, 'green' ] ]
for (const [i, el] of colors.entries()) {
console.log(i)
console.log(el)
/*
0
red
1
blue
2
green
*/
}
迭代器方法 |
返回值 |
keys() |
数组索引的迭代器 |
values() |
数组元素的迭代器 |
entries() |
索引/值对的迭代器 |
复制和填充方法
- ES6 新增填充数组方法
fill()
,在指定范围内(包含开始索引,不包含结束索引),向已有数组中插入全部或部分相同的值,不改变原数组大小
- 参数一:要插入的值,非必填,若不填自动转为 undefined
- 参数二:开始索引(包含),非必填,若不填则全部填充;若负数则想象成数组长度加上这个值
- 参数三:结束索引(不包含),非必填,若不填则一直填充到数组末尾;若负数则想象成数组长度加上这个值
let zeros = [0, 0, 0, 0, 0]
zeros.fill(5) // 用5填充整个数组,省略了开始索引和结束索引
console.log(zeros) // [ 5, 5, 5, 5, 5 ]
zeros.fill(0) // 重置
zeros.fill(6, 3) // 用6填充索引大于等于3的元素,省略了结束索引
console.log(zeros) // [ 0, 0, 0, 6, 6 ]
zeros.fill(0) // 重置
zeros.fill(7, 1, 3) // 用7填充索引值大于等于1且小于3的元素
console.log(zeros) // [ 0, 7, 7, 0, 0 ]
zeros.fill(0) // 重置
zeros.fill(8, -4, 3) // 相当于zeros.fill(8, 5-4, 3),用8填充索引值大于等于1且小于3的元素
console.log(zeros) // [ 0, 8, 8, 0, 0 ]
zeros.fill(0) // 重置
fill()
静默忽略:超出数组边界、零长度、索引范围方向相反,若索引部分可用则填充可用部分
zeros.fill(1, -10, -6) // 相当于zeros.fill(1, 5-10, 5-6),超出数组边界,忽略
console.log(zeros) // [ 0, 0, 0, 0, 0 ]
zeros.fill(0) // 重置
zeros.fill(1, 10, 15) // 超出数组边界,忽略
console.log(zeros) // [ 0, 0, 0, 0, 0 ]
zeros.fill(0) // 重置
zeros.fill(2, 4, 2) // 索引反向,忽略
console.log(zeros) // [ 0, 0, 0, 0, 0 ]
zeros.fill(0) // 重置
zeros.fill(4, 3, 10) // 索引部分可用,填充可用部分
console.log(zeros) // [ 0, 0, 0, 4, 4 ]
zeros.fill(0) // 重置
- ES6 新增批量复制方法
copyWithin()
,在指定范围内(包含开始索引,不包含结束索引),浅复制数组中的部分内容,并将复制内容从指定索引开始替换,不改变原数组大小
- 参数一:从该索引开始替换,必填
- 参数二:开始索引(包含),非必填,若不填则默认为 0;若负数则想象成数组长度加上这个值
- 参数三:结束索引(不包含),非必填,若不填则一直填充到数组末尾;若负数则想象成数组长度加上这个值
zeros = [1, 2, 3, 4, 5]
zeros.copyWithin(2) // 浅复制整个数组,从索引为2开始替换(直到数组边界),省略了开始索引和结束索引
console.log(zeros) // [ 1, 2, 1, 2, 3 ]
zeros = [1, 2, 3, 4, 5] // 重置
zeros.copyWithin(4, 3) // 浅复制索引大于等于3到数组结束的元素,从索引为4开始替换(直到数组边界),省略了结束索引
console.log(zeros) // [ 1, 2, 3, 4, 4 ]
zeros = [1, 2, 3, 4, 5] // 重置
zeros.copyWithin(3, 1, 3) // 浅复制索引大于等于1且小于3的元素,从索引为3开始替换(直到数组边界)
console.log(zeros) // [ 1, 2, 3, 2, 3 ]
zeros = [1, 2, 3, 4, 5] // 重置
zeros.copyWithin(2, -4, -1) // 相当于zeros.copyWithin(2, 5-4, 5-1),浅复制索引大于等于1且小于4的元素,从索引为2开始替换(直到数组边界)
console.log(zeros) // [ 1, 2, 2, 3, 4 ]
zeros = [1, 2, 3, 4, 5] // 重置
- 同
fill()
,copyWithin()
也会静默忽略:超出数组边界、零长度、索引范围方向相反,若索引部分可用则填充可用部分
zeros.copyWithin(2, -15, -12) // 相当于zeros.copyWithin(2, 5-15, 5-12),超出数组边界,忽略
console.log(zeros) // [ 1, 2, 3, 4, 5 ]
zeros = [1, 2, 3, 4, 5] // 重置
zeros.copyWithin(2, 12, 15) // 超出数组边界,忽略
console.log(zeros) // [ 1, 2, 3, 4, 5 ]
zeros = [1, 2, 3, 4, 5] // 重置
zeros.copyWithin(2, 3, 1) // 索引反向,忽略
console.log(zeros) // [ 1, 2, 3, 4, 5 ]
zeros = [1, 2, 3, 4, 5] // 重置
zeros.copyWithin(2, 3, 6) // 索引部分可用,填充可用部分
console.log(zeros) // [ 1, 2, 4, 5, 5 ]
zeros = [1, 2, 3, 4, 5] // 重置
复制和填充数组 |
含义 |
参数 |
fill() |
指定范围内向数组插入相同的值 |
① 要插入的值 ② 开始索引(包含) ③ 结束索引(不包含) |
copyWithin() |
浅复制数组指定范围内容,从指定索引开始替换 |
① 从该索引开始替换 ② 开始索引(包含) ③ 结束索引(不包含) |
转换方法
- 所有对象都有
toLocaleString()
、toString()
和valueOf()
方法:
valueOf()
返回数组本身
toString()
对数组每个值调用其toString()
方法,返回由逗号分隔拼接而成的字符串
toLocaleString()
对数组每个值调用其toLocaleString()
方法,返回由逗号分隔拼接而成的字符串
colors = ['red', 'blue', 'green']
console.log(colors) // [ 'red', 'blue', 'green' ]
console.log(colors.valueOf()) // [ 'red', 'blue', 'green' ]
console.log(colors.toString()) // red,blue,green
console.log(colors.toLocaleString()) // red,blue,green
// toLocaleString() vs toString()
let person1 = {
toLocaleString() {
return 'Nikalaos'
},
toString() {
return 'Nicholas'
},
}
let person2 = {
toLocaleString() {
return 'Grigorios'
},
toString() {
return 'Greg'
},
}
let people = [person1, person2]
console.log(people.toString()) // Nicholas,Greg
console.log(people.toLocaleString()) // Nikalaos,Grigorios
join()
对数组每个值调用其toString()
方法,接收一个参数作为设定数组返回拼接字符串的分隔符
console.log(colors.join()) // red,blue,green,默认用逗号拼接
console.log(colors.join(undefined)) // red,blue,green,默认用逗号拼接
console.log(colors.join('|')) // red|blue|green
console.log([undefined, 1, 2].join()) // ,1,2
数组转换 |
返回 |
参数 |
valueOf() |
数组本身 |
|
toString() |
对每个值调用toString() ,返回逗号拼接的字符串 |
|
toLocaleString() |
对每个值调用toLocaleString() ,返回逗号拼接的字符串 |
|
join() |
对每个值调用toString() ,返回指定分隔符拼接的字符串 |
指定分隔符 |
设定数组返回拼接字符串的分隔符
栈方法
colors = new Array()
console.log(colors.push('red', 'blue')) //2,返回数组的长度
pop()
方法用于删除数组的最后一项,返回被删除的项
console.log(colors.pop()) // 'blue',返回被删除的项
栈方法 |
操作 |
返回 |
参数 |
push() |
数组末尾添加项 |
数组的最新长度 |
要添加的项 |
pop() |
删除数组最后一项 |
被删除的项 |
|
队列方法
- 队列是先进先出的结构,对应的方法是
shift()
和unshift()
shift()
方法用于删除数组的开头一项,返回被删除的项
colors = new Array()
colors.push('red', 'blue')
console.log(colors.shift()) // 'red',返回被删除的项
unshift()
方法接收任意数量的参数,并将它们添加到数组开头,返回数组的最新长度
console.log(colors.unshift('green', 'black')) // 3,返回数组的长度
console.log(colors) // [ 'green', 'black', 'blue' ]
栈方法 |
操作 |
返回 |
参数 |
shift() |
删除数组开头一项 |
被删除的项 |
|
unshift() |
数组开头添加项 |
数组的最新长度 |
要添加的项 |
排序方法
let values = [1, 2, 3, 4, 5]
values.reverse()
console.log(values) // [ 5, 4, 3, 2, 1 ]
sort()
方法会在每一项上调用String()
转型函数,然后比较字符串按序重新排列数组元素(默认升序)
values = [0, 1, 5, 10, 15]
values.sort()
console.log(values) // [ 0, 1, 10, 15, 5 ],比较字符串大小而不是数字大小
-
sort()
方法可以接收一个比较函数,用于判断数组中数值的排列顺序,比较函数接收 2 个参数(以升序为例):
- 如果第 1 个参数应该排在第二个参数前面,则返回负值
- 如果 2 个参数相等,则返回 0
- 如果第 1 个参数应该排在第二个参数后面,则返回正值
function compareAsc(val1, val2) {
if (val1 < val2) {
return -1
} else if (val1 > val2) {
return 1
} else {
return 0
}
}
values = [0, 1, 5, 10, 15]
values.sort(compareAsc) // 接收参数:正序比较函数
console.log(values) // [ 0, 1, 5, 10, 15 ]
function compareDesc(val1, val2) {
if (val1 < val2) {
return 1 // 降序
} else if (val1 > val2) {
return -1 // 降序
} else {
return 0
}
}
values.sort(compareDesc) // 接收参数:降序比较函数
console.log(values) // [ 15, 10, 5, 1, 0 ]
values.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)) // 升序
console.log(values) // [ 0, 1, 5, 10, 15 ]
- 如果数组的元素是数值或 valueOf()方法返回数值的对象(如 Date 对象),比较函数可进一步简化为减法操作,用第 1 个参数减去第 2 个参数(或相反)
values.sort((a, b) => a - b) // 升序
console.log(values) // [ 0, 1, 5, 10, 15 ]
values.sort((a, b) => b - a) // 降序
console.log(values) // [ 15, 10, 5, 1, 0 ]
排序方法 |
操作 |
返回 |
参数 |
reverse() |
数组元素反向排列 |
调用数组的引用 |
|
sort() |
数组元素按序排列 |
调用数组的引用 |
比较函数,用于判断排列顺序 |
操作方法
concat()
创建当前数组的副本,然后把它的参数添加到数组末尾,返回新构建的数组,不改变原数组
- 若参数是一个或多个数组,则把这些数组的每一项都添加到结果数组末尾
- 若参数不是数组,则直接把它们添加到结果数组末尾
colors = ['red', 'green', 'blue']
let colors2 = colors.concat('yellow', ['black', 'brown'])
console.log(colors) // [ 'red', 'green', 'blue' ],不改变原数组
console.log(colors2) // [ 'red', 'green', 'blue', 'yellow', 'black', 'brown' ]
let colors3 = colors.concat('yellow', ['black', 'brown', ['orange']]) // [ 'red', 'green', 'blue', 'yellow', 'black', 'brown', [ 'orange' ] ]
console.log(colors3)
- 在参数数组上指定特殊的符号
Symbol.isConcatSpreadable
,设置为 false 可阻止打平数组(数组默认打平),设置为 true 可打平类数组对象(类数组对象默认不打平)
let newColors = ['black', 'brown'] // 数组
let moreNewColors = {
// 类数组对象
0: 'pink',
1: 'cyan',
length: 2,
}
console.log(colors.concat(newColors)) // [ 'red', 'green', 'blue', 'black', 'brown' ],数组默认打平
console.log(colors.concat(moreNewColors)) // [ 'red', 'green', 'blue', { '0': 'pink', '1': 'cyan' } ],类数组对象默认不打平
newColors[Symbol.isConcatSpreadable] = false // 阻止打平数组
moreNewColors[Symbol.isConcatSpreadable] = true // 强制打平类数组对象
console.log(colors.concat(newColors)) // [ 'red', 'green', 'blue',[ 'black', 'brown', [Symbol(Symbol.isConcatSpreadable)]: false] ]
console.log(colors.concat(moreNewColors)) // [ 'red', 'green', 'blue', 'pink', 'cyan' ]
slice()
创建一个包含原有数组中若干元素的新数组,不改变原数组,接收 1 个或 2 个参数(开始索引&结束索引)
- 1 个参数,返回该索引到数组末尾的所有元素
- 2 个参数,返回从开始索引到结束索引的所有元素,不包含结束索引
- 同
fill()
和copyWithin()
,索引负值则以数组长度加上负值即可
colors = ['red', 'green', 'blue', 'black', 'brown']
console.log(colors.slice(1)) // [ 'green', 'blue', 'black', 'brown' ],索引大于等于1到末尾的元素
console.log(colors.slice(1, 4)) // [ 'green', 'blue', 'black' ],索引大于等于1小于4的元素
splice()
可在数组中插入元素、删除元素或同时进行插入和删除两种操作,返回被删除元素组成的数组,改变原数组
- 删除元素,传入 2 个参数:要操作元素的开始位置、要删除元素数量
- 插入(并删除)元素,传入大于等于 3 个参数:要操作元素的开始位置、要删除元素数量(0 则不删除)、要插入的元素 1、要插入的元素 2…
colors = ['red', 'green', 'blue']
let removed = colors.splice(0, 1) // 从索引0开始,删除1项
console.log(removed) // [ 'red' ],返回被删除元素组成的数组
console.log(colors) // [ 'green', 'blue' ],改变原数组
removed = colors.splice(1, 0, 'yellow', 'orange') // 从索引1开始,删除0项,插入'yellow'、'orange'
console.log(removed) // [],没有被删除的元素
console.log(colors) // [ 'green', 'yellow', 'orange', 'blue' ]
removed = colors.splice(1, 1, 'black', 'purple') // 从索引1开始,删除1项,插入'black'、'purple'
console.log(removed) // [ 'yellow' ]
console.log(colors) // [ 'green', 'black', 'purple', 'orange', 'blue' ]
操作方法 |
操作 |
返回 |
参数 |
改变原数组 |
concat() |
数组末尾追加元素 |
新数组 |
要添加的元素/数组 |
否 |
slice() |
创建包含原数组若干元素的新数组 |
新数组 |
① 开始索引 ② 结束索引(不包含) |
否 |
splice() |
数组(同时)插入元素、删除元素 |
被删除元素组成的数组 |
① 开始索引 ② 要删除个数 ③ 插入元素 1 ④ 插入元素 2 |
是 |
搜索和位置方法
- ECMASctipr 提供 2 类搜索数组的方法:严格相等搜索和断言函数搜索
严格相等
- 3 个方法:
indexOf()
、lastIndexOf()
、includes()
- 均接收 2 个参数:要查找的元素(必填)、起始搜索位置(非必填)
indexOf()
和includes()
从前向后搜索,lastIndexOf()
从后向前搜索
indexOf()
、lastIndexOf()
返回要查找元素首次出现的位置(无匹配返回-1),includes()
返回布尔值
- 查找时,均使用
===
全等比较
includes()
是 ES7 新增的方法
let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1]
console.log(numbers.indexOf(4)) // 3,从前向后,数组首次出现4的索引
console.log(numbers.lastIndexOf(4)) // 5,从后向前,数组首次出现4的索引
console.log(numbers.includes(4)) // true,从前向后,数组中是否包含4
console.log(numbers.indexOf(4, 4)) // 5,从前向后,从数组索引4开始首次出现4的索引
console.log(numbers.lastIndexOf(4, 4)) // 3,从后向前,从数组索引4开始首次出现4的索引
console.log(numbers.includes(4, 7)) // false,从前向后,从数组索引7开始是否包含4
let man = { name: 'Nicholas' }
let human = [{ name: 'Nicholas' }] // 不全等,human数组中的对象和对象man来自不同的引用
let human2 = [man] // 全等,将对象man放入human2数组
console.log(human.indexOf(man)) // -1
console.log(human2.indexOf(man)) // 0
console.log(human.includes(man)) // false
console.log(human2.includes(man)) // true
严格相等 |
参数 |
查找顺序 |
返回 |
indexOf() |
① 要查找元素(必) ② 起始搜索位置(非) |
前 → 后 |
要查找元素首次出现的位置,无匹配返回-1 |
lastIndexOf() |
① 要查找元素(必) ② 起始搜索位置(非) |
后 → 前 |
要查找元素首次出现的位置,无匹配返回-1 |
includes() |
① 要查找元素(必) ② 起始搜索位置(非) |
前 → 后 |
布尔值 |
断言函数
- 2 个方法:
find()
和findIndex()
- 均接收 2 个参数:断言函数、指定断言函数内部 this 的值(可选)
- 断言函数又接收 3 个参数:元素、索引、数组本身
find()
返回第一个匹配的元素,无匹配返回 undefined
findIndex()
返回第一个匹配元素的索引,无匹配返回-1
people = [
{ name: 'Matt', age: 27 },
{ name: 'Nicholas', age: 29 },
]
console.log(people.find((e, i, arr) => e.age > 28)) // { name: 'Nicholas', age: 29 },返回元素
console.log(people.findIndex((e, i, arr) => e.age > 28)) // 1,返回索引
console.log(people.find((e, i, arr) => e.age > 30)) // undefined,无匹配
console.log(people.findIndex((e, i, arr) => e.age > 30)) // -1,无匹配
numbers = [3, 6, 9]
numbers.find((e, i, arr) => {
console.log(e)
console.log(i)
console.log(arr)
return e % 2 === 0 // 匹配条件:元素能被2整除
/*
开始搜索:
3,不符合匹配条件
0,此时的索引
[ 3, 6, 9 ],此时的数组
继续搜索:
6,符合匹配条件
1,此时的索引
[ 3, 6, 9 ],次数的数组
不再继续搜索
*/
})
断言函数 |
参数 |
返回 |
find() |
① 断言函数(必) ② 指定断言函数内部 this 的值(非) |
第一个匹配的元素,无匹配返回 undefined |
findIndex() |
① 断言函数(必) ② 指定断言函数内部 this 的值(非) |
第一个匹配元素的索引,无匹配返回-1 |
迭代方法
- 5 个方法
every()
、some()
、filter()
、map()
、forEach()
- 每个方法接收 2 个参数:以每一项为参数运行的函数、作为函数运行上下文的作用域对象(非必填,影响函数中 this 的值)
- 传给每个方法的函数接收 3 个参数:元素、索引、数组本身
every()
:对数组每一项运行传入的函数,若每项都返回 true,则该方法返回 true
some()
:对数组每一项运行传入的函数,若有一项返回 true,则该方法返回 true
filter()
:对数组每一项运行传入的函数,由返回 true 的项组成数组,返回给该方法
map()
:对数组每一项运行传入的函数,由每项调用的结果组成数组,返回给该方法
forEach()
:对数组每一项运行传入的函数,相当于使用 for 循环遍历数组,该方法没有返回值
- 除了
forEach()
,其他 4 种方法的参数运行函数都必须有 return(或取消大括号的箭头函数)
numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1]
// some()
let everyResult = numbers.every((item, index, array) => item > 2) // 是否每项都大于2
console.log(everyResult) // false
let someResult = numbers.some((item, index, array) => item > 2) // 是否有1项大于2
console.log(someResult) // true
// filter()
let filterResult = numbers.filter((item, index, array) => item > 2) // 筛选出大于2的元素
console.log(filterResult) // [ 3, 4, 5, 4, 3 ]
// map()
let mapResult = numbers.map((item, index, array) => item * 2) // 返回每项调用函数的结果
console.log(mapResult) // [ 2, 4, 6, 8, 10, 8, 6, 4, 2 ]
// forEach()
let forEachResult = numbers.forEach((item, index, array) => {
item = item * 2
})
console.log(forEachResult) // undefined,forEach没有返回值
numbers.forEach((item, index, array) => {
// 在函数内执行操作,相当于使用for循环遍历
console.log(item * 2)
/*
2
4
6
8
10
8
6
4
2
*/
})
迭代方法 |
参数 |
返回 |
every() |
① 运行函数(必),必须有返回值 ② 函数的作用域对象(非) |
每项运行参数函数,每项都返回 true 方法才返回 true |
some() |
① 运行函数(必),必须有返回值 ② 函数的作用域对象(非) |
每项运行参数函数,有一项返回 true 方法就返回 true |
filter() |
① 运行函数(必),必须有返回值 ② 函数的作用域对象(非) |
每项运行参数函数,返回 由返回 true 的项组成的数组 |
map() |
① 运行函数(必),必须有返回值 ② 函数的作用域对象(非) |
每项运行参数函数,返回 由每项调用的结果组成的数组 |
forEach() |
① 运行函数(必),没有返回值 ② 函数的作用域对象(非) |
无返回值 |
归并方法
- 2 个方法
reduce()
和reduceRight()
,均迭代数组的所有项,在此基础上构建一个最终返回值
- 每个方法接收 2 个参数:对每一项都会运行的归并函数、归并起点的初始值(非必填)
- 每个归并函数接收 4 个参数:上一个归并值、当前项、当前索引、数组本身
- 若省略归并起点值,则首次迭代将从数组第 2 项开始,传给归并函数的第 1 个参数是数组第 1 项,第 2 个参数是数组第 2 项
reduce()
从前向后遍历,reduceRight()
反之
values = [1, 2, 3, 4, 5]
// reduce()
let sum1 = values.reduce((pre, cur, index, arr) => {
console.log(pre, cur, index)
/*
1 2 1
3 3 2
6 4 3
10 5 4
*/
return pre + cur
}) // 省略归并起点值,归并函数第1个参数为数组第2项,第2个参数为数组第2项
console.log(sum1) // 15
let sum2 = values.reduce((pre, cur, index, arr) => {
console.log(pre, cur, index)
/*
10 1 0
11 2 1
13 3 2
16 4 3
20 5 4
*/
return pre + cur
}, 10) // 归并起点值为10,归并函数第1个参数为10,第2个参数为数组第1项
console.log(sum2) // 25
// reduceRight
let sum3 = values.reduceRight((pre, cur, index, arr) => {
console.log(pre, cur, index)
/*
5 4 3
9 3 2
12 2 1
14 1 0
*/
return pre + cur
})
console.log(sum3) // 15
let sum4 = values.reduceRight((pre, cur, index, arr) => {
console.log(pre, cur, index)
/*
10 5 4
15 4 3
19 3 2
22 2 1
24 1 0
*/
return pre + cur
}, 10) // 归并起点值为10,归并函数第1个参数为10,第2个参数为数组最后1项
console.log(sum4) // 25
迭代方法 |
参数 |
遍历方向 |
返回 |
reduce() |
① 归并函数(必) ② 归并起点值(非) |
前 → 后 |
遍历后最终返回值 |
reduceRight() |
① 运行函数(必) ② 归并起点值(非) |
后 → 前 |
遍历后最终返回值 |
总结 & 问点
- 有哪些基本方法可以创建数组?如何将类数组或一组参数转换为数组实例?
- 为什么不建议使用数组空位?如果确实需要呢?
- 数组的 length 属性是可变的么?如何快速的向数组末尾添加元素?
- 如何判断一个对象是不是数组?
- 用什么方法获取数组索引组成的数组?元素和键值对呢?
- 用什么方法批量填充数组的部分内容?用什么方法获取数组每个值拼接的字符串?若指定分隔符呢?
- 数组的“栈方法”和“队列方法”分别是怎样的用法和返回值?
- 如何按照升序/降序排列数组元素?如果数组元素是数值,如何简化写法?
- 如何将数组和类数组对象打平后添加到另一个数组的末尾?不打平添加呢?
- 请详述 slice()和 splice()的含义、用法、返回值及是否改变原数组
- 有哪些方法可以搜索数组?请分别详述其用法并举例
- 有哪些数组迭代方法?请分别详述其用法并举例
- 有哪些数组归并方法?请分别详述其用法并举例