随着JavaScript
的发展,JavaScript
的Array
也增加了许多方法。有必要全面了解一下。本文基本涵盖了Array
所有的方法介绍。
一、 检测方法
Array.isArray()
判断传入的值是否是一个数组。
// true
Array.isArray([1, 2, 3])
// false
Array.isArray({foo: 123})
// false
Array.isArray('foobar')
// false
Array.isArray(undefined)
二、 创建数组方法
Array.from()
Array.from()
方法用于将类数组对象
和可迭代对象
转为真正的数组,并且返回一个新的,浅拷贝
的数组实例。
// 报错
Array.from(undefined)
// 报错
Array.from(null)
// ["f", "o", "o"]
console.log(Array.from('foo'))
// []
console.log(Array.from(''))
// []
console.log(Array.from(123))
// []
console.log(Array.from(NaN))
// arguments对象转为数组
function foo() {
const args = Array.from(arguments)
//true
console.log(Array.isArray(args))
}
foo(1, 2, 3)
// NodeList对象转为数组
Array.from(document.querySelectorAll('p'))
// Set对象转为数组:['a','b']
Array.from(new Set(['a', 'b']))
// Map对象转为数组:[[1, 2], [2, 4]]
Array.from(new Map([[1, 2], [2, 4]]))
Array.from()
可以传入3
个参数:
-
第一个参数(必填):想要转换成数组的类数组对象或可迭代对象。
-
第二个参数(可选):数组中的每个元素会执行该回调函数。
-
第三个参数(可选):执行第二个参数回调函数时需要绑定的
this
对象。// 传入第二个参数回调函数:[2, 4, 6] Array.from([1, 2, 3], x => x + x)
let obj = { num: 1, handle: function(value){ return n + this.num } } // 传入第三个参数修改this指向:[2, 3, 4, 5, 6] const arrs = Array.from([1, 2, 3, 4, 5], obj.handle, obj)
// 得到数组对象里的id属性:[1, 2] const obj = [{id: 1,name: 'zhangsan'},{id: 2,name: 'lisi'}] Array.from(obj,(el) => { return el.id })
注意:
Array.from(null)
或者Array.from(undefined)
会抛出异常
Array.of()
Array.of()
创建一个包含所有传入参数的数组,不考虑参数的数量或类型,返回一个新数组。
使用Array.of()
创建新数组:
Array.of() // []
Array.of(undefined) // [undefined]
Array.of(null) // [null]
Array.of(NaN) // [NaN]
Array.of(1) // [1]
Array.of(1, 2) // [1, 2]
Array.of([1,2,3]) // [[1,2,3]]
Array.of({id: 1},{id: 2}) // [{id:1}, {id:2}]
三、 遍历(迭代)方法
forEach()
对数组中的每一项运行指定的函数。这个方法返回undefined
,即使你return
了一个值。
Array.forEach()
参数语法:
- 第一个参数(必填):
callback
在数组每一项上执行的函数。该函数接收三个参数:
element
index
array
当前元素
当前元素的索引 (可选)
数组本身(可选)
-
第二个参数(可选):当执行回调函数时用作 this 的值。
const arr = [{id: 1,name: 'zhangsan'},{id: 2,name: 'lisi'}] // 1 - zhangsan // 2 - lisi arr.forEach(el => { console.log(`${el.id} - ${el.name}`); }); const obj = { handle: function(n){ return n + 2 } }; // true [{id: 1,name: 'zhangsan'},{id: 2,name: 'lisi'}].forEach(function(el,index,arr){ if(el.id === 1) { return } console.log(this === obj) },obj);
Array.forEach()
不能中断循环(使用break
,或continue
语句)。只能用return
退出本次回调,进行下一次回调。
map()
返回一个新数组,结果是该数组中的每个元素都调用提供的函数后返回的结果。
Array.map()
参数语法:
- 第一个参数(必填):
callback
生成新数组元素的函数。该函数接收三个参数:
element
index
array
当前元素
当前元素的索引 (可选)
数组本身(可选)
-
第二个参数(可选):当执行回调函数时用作
this
的值。const arr = [{id: 1},{id: 2},{id: 3}] const newArr = arr.map((el,index,arr) => { el.age = 20 return el }); //[{id: 1,age: 20},{id: 2,age: 20},{id: 3,age: 20}] console.log(newArr);
filter()
对数组中的每一项运行指定的函数,返回该函数会返回true
的项组成的新的数组。如果没有任何数组元素通过测试,则返回空数组。
Array.filter()
参数语法:
- 第一个参数(必填):
callback
用来测试数组的每个元素的函数。返回true
表示该元素通过测试,保留该元素,false
则不保留。该函数接收三个参数:
element
index
array
当前元素
当前元素的索引 (可选)
数组本身(可选)
-
第二个参数(可选):当执行回调函数时用作
this
的值。const arr = [{id: 1},{id: 2},{id: 3}] const newArr = arr.filter((el,index,arr) => { el.age = 20 return el }); // [{id: 1,age: 20},{id: 2,age: 20},{id: 3,age: 20}] console.log(newArr);
some()
检测数组中的是否有满足判断条件的元素。
对数组中的每一项运行指定的函数,如果该函数对任一项返回true
,则返回true
,并且剩余的元素不会再执行检测。如果没有满足条件的元素,则返回false
。
Array.some()
参数语法:
- 第一个参数(必填):
callback
用来测试每个元素的函数。该函数接收三个参数:
element
index
array
当前元素
当前元素的索引 (可选)
数组本身(可选)
-
第二个参数(可选):当执行回调函数时用作
this
的值。const arr = [{id: 1},{id: 2},{id: 3}] const someResult = arr.some((el,index,arr) => { return el.id === 1 }); // true console.log(someResult)
every()
检测数组所有元素是否都符合判断条件。
对数组中的每一项运行指定的函数,如果该函数对每一项都返回true
,则返回true
。若收到一个空数组,此方法在一切情况下都会返回true
。如果数组中检测到有一个元素不满足,则返回 false
,且剩余的元素不会再进行检测。
Array.every()
参数语法:
- 第一个参数(必填):
callback
用来测试每个元素的函数。该函数接收三个参数:
element
index
array
当前元素
当前元素的索引 (可选)
数组本身(可选)
-
第二个参数(可选):当执行回调函数时用作
this
的值。// true [].every(() => {}) const arr = [{id: 1},{id: 2},{id: 3}] const everyResult = arr.every((el,index,arr) => { return el.id > 0 }); // true console.log(everyResult)
find()
返回数组中匹配的第一个元素的值,否则返回undefined
。
Array.find()
参数语法:
- 第一个参数(必填):
callback
在数组每一项上执行的函数。该函数接收三个参数:
element
index
array
当前元素
当前元素的索引 (可选)
数组本身 (可选)
-
第二个参数(可选):当执行回调函数时
this
的值。const arr = [{id: 1},{id: 2},{id: 3}] const findResult = arr.find((el,index,arr) => { return el.id === 1 },obj); // {id: 1} console.log(findResult)
findIndex()
返回数组中匹配的第一个元素的索引。否则返回-1
。
Array.findIndex()
参数语法:
- 第一个参数(必填):
callback
在数组每一项上执行的函数。该函数接收三个参数:
element
index
array
当前元素
当前元素的索引值
数组本身
-
第二个参数(可选):当执行回调函数时
this
的值。const arr = [{id: 1},{id: 2},{id: 3}] // 2 const findResult = arr.findIndex((el,index,arr) => { return el.id === 3 },obj)
entries()
、keys()
、values()
用于遍历数组,它们都返回一个遍历器Array Iterator
对象。可以用for...of
循环进行遍历,他们的区别是keys()
是对键名的遍历、values()v是对键值的遍历
,entries()`是键值对的遍历。
// 0
// 1
for (let i of ['a', 'b'].keys()) {
console.log(i)
}
// a
// b
for (let el of ['a', 'b'].values()) {
console.log(el)
}
// 0-a
// 1-b
for (let [i, el] of ['a', 'b'].entries()) {
console.log(`${i}-${el}`)
}
可以手动调用遍历器对象的next
方法,进行遍历。
const arr = ['a', 'b', 'c']
const tempIterator = arr.entries()
// [0, "a"]
console.log(tempIterator.next().value)
// [1, "b"]
console.log(tempIterator.next().value)
四、操作方法
push()
将一个或多个元素添加到数组的末尾,并返回该数组的新长度。
var numbers = [1, 2, 3]
// 5
console.log(numbers.push(4,5))
// [1,2,3,4,5]
console.log(numbers)
pop()
从数组中删除最后一个元素,并返回删除的元素。
const arr = ['a', 'b', 'c']
// c
console.log(arr.pop())
// ["a", "b"]
console.log(arr);
shift()
shift() 方法从数组中删除第一个元素,并返回删除的元素。
const arr = ['a', 'b', 'c']
// a
console.log(arr.shift())
// ["b", "c"]
console.log(arr)
unshift()
将一个或多个元素添加到数组的开头,并返回该数组的新长度(该方法修改原有数组)。
const arr = ['a', 'b', 'c']
// 5
console.log(arr.unshift('d', 'e'))
// ["d", "e", "a", "b", "c"]
console.log(arr)
concat()
用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。如果省略参数,则concat会返回当前数组的浅拷贝。
const arr = [1, 2, 3]
const newArr = arr.concat()
// [1,2,3]
console.log(newArr)
// false
console.log(newArr === arr)
const arr = [1, 2, 3]
const newArr = arr.concat([4, 5])
// [1, 2, 3, 4, 5]
console.log(newArr)
indexOf()
、lastIndexOf()
这两个方法都返回要查找的元素在数组中的位置,或者在没找到的情况下返回-1
。indexOf()
方法从数组的开头开始向后查找,lastIndexOf()
方法则从数组的末尾开始向前查找。
Array.indexOf()、Array.lastIndexOf()
参数语法:
- 第一个参数
searchElement
(可选):被查找的元素。 - 第二个参数
fromIndex
(可选):indexOf()
方法表示开始向后查找的位置。默认值为0
。lastIndexOf()
方法表示从此位置开始逆向查找。默认为数组的长度减 1 (arr.length - 1
)。
indexOf()
const numbers = [1, 2, 3, 4, 5, 4]
// 3
console.log(numbers.indexOf(4))
// 5
console.log(numbers.indexOf(4, 4))
lastIndexOf()
const numbers = [1, 2, 3, 4, 5, 4]
// 5
console.log(numbers.lastIndexOf(4))
// 3
console.log(numbers.lastIndexOf(4, 4))
slice()
创建一个新的数组并返回。该方法接受两个参数:是一个由起始索引和结束索引的提取出来的原数组的浅拷贝。原始数组不会被改变。
Array.slice()
参数语法:
-
第一个参数(可选):起始索引
begin
(默认从0
开始),从该索引开始提取原数组元素。 -
第二个参数(可选):结束索引
end
在该索引结束提取原数组元素。如果该参数省略,则一直提取到原数组末尾结束。slice
会提取原数组中begin
到end
的所有元素(包含begin
,但不包含end
)。const arr = [1, 2, 3, 4] const newArr = arr.slice(1) // [2,3,4] console.log(newArr); const newArr1 = arr.slice(1, 3) // [2,3] console.log(newArr1)
如果结束位置小于起始位置,则返回空数组。
const arr = [1, 2, 3, 4]
const newArr = arr.slice(2, 1)
// []
console.log(newArr)
splice()
向数组的中删除
、插入
、替换元素
。返回值是被删除的元素组成的一个数组。如果没有删除元素,则返回空数组。此方法会改变原数组。
删除任意数量的元素,传入 2
个参数,要删除的元素开始索引和要删除的个数。
const arr = [{ id: 1 }, { id: 2 }, { id: 3 }]
//删除前两个元素
arr.splice(0, 2)
// [{id: 3}]
console.log(arr)
向指定位置插入任意数量的元素,传入3
个参数:起始位置、0
(要删除的元素个数) 和要插入的元素。如果要插入多个元素,可以再传入第四、第五,以至任意多个元素。
const arr = [{ id: 1 }, { id: 2 }, { id: 3 }]
// 从索引 1 开始插入两个元素
arr.splice(1, 0, { id: 4 }, { id: 5 })
// [{ id: 1 }, { id: 4 }, { id: 5 },{ id: 2 }, { id: 3 }]
console.log(arr)
向指定位置插入任意数量的元素,且同时删除任意数量的元素。传入3
个参数:起始位置、要删除的元素个数和要插入的元素。
const arr = [{ id: 1 }, { id: 2 }, { id: 3 }]
// 从索引 1 开始,删除一个元素,并切插入两个元素
arr.splice(1, 1, { id: 4 }, { id: 5 })
// [{ id: 1 }, { id: 4 }, { id: 5 },{ id: 3 }]
console.log(arr)
copyWithin()
在数组内部替换自身元素,返回修改后的当前数组。
Array.copyWithin()
参数语法:
-
第一个参数(必填):从该位置开始替换元素。
-
第二个参数(可选):从该位置开始复制数据,默认为
0
。 -
第三个参数(可选):停止复制的索引(不包含自身),默认值为数组的长度。
// 将数组的前两个元素替换数组的最后两个位置:[1,2,1,2] // 从索引2的位置开始替换 // 从索引0的位置开始复制数据 [1, 2, 3, 4].copyWithin(2,0)
const arr = [{id: 1},{id: 2},{id: 3}] // [{id: 3},{id: 2},{id: 3}] arr.copyWithin(0, 2)
// 从索引2的位置开始替换 // 从索引0的位置开始复制 // 在遇到索引1的时候停止复制(不包含自身) // [1,2,1,4] [1, 2, 3, 4].copyWithin(2,0)
fill()
使用固定值填充一个数组中一个或多个元素。
- 第一个参数:用来填充数组元素的值。
- 第二个参数(可选):起始索引,默认值为
0
。 - 第二个参数(可选):终止索引,默认值为数组的长度。
当传入一个参数的时候,会用这个参数的值填充整个数组:
const arr = [{ id: 1 }, { id: 2 }, { id: 3 }]
arr.fill({ id: 4 })
// [{ id: 4 }, { id: 4 }, { id: 4 }]
console.log(arr)
// true
console.log(arr[0] === arr[1])
当传入多个个参数的时候,用这个参数的值填充部分数组:
const arr = [{ id: 1 }, { id: 2 }, { id: 3 }]
// 从数组下标索引为1的元素开始填充
arr.fill({ id: 4 }, 1)
// [{ id: 1 }, { id: 4 }, { id: 4 }]
console.log(arr)
// 填充的元素不包括终止的索引元素。
const numbers = [1, 2, 3, 4]
numbers.fill(0, 1, 2)
// [1, 0, 3, 4]
console.log(numbers)
flat()
将嵌套的数组,变成一维的数组。返回一个新数组。
Array.flat()
参数语法:
- 第一个参数(可选):指定要提取嵌套数组的结构深度,默认值为 1。
展开一层
const arr = [1, 2, [3, 4]]
const newArr = arr.flat()
//[1,2,3,4]
console.log(newArr)
展开两层
const arr = [1, 2, [3, [4, 5]]]
const newArr = arr.flat(2)
// [1, 2, 3, 4, 5]
console.log(newArr)
使用 Infinity,可展开任意深度的嵌套数组
var arr = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
const newArr = arr.flat(Infinity)
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(newArr)
移除数组中的空项
var arr = [1, 2, , 4, 5]
const newArr = arr.flat()
// [1, 2, 4, 5]
console.log(newArr)
flatMap()
对原数组的每个成员执行一个函数,然后对返回值组成的数组执行flat()方法。该方法返回一个新数组,不改变原数组。
Array.flatMap()
参数语法:
- 第一个参数(必填):
callback
遍历函数。该函数接收三个参数:
element
index
array
当前元素
当前元素的索引(可选)
数组对象本身(可选)
-
第二个参数(可选):当执行回调函数时this的值。
var arr = [1, 2] const newArr = arr.flatMap(el => [el, el * 2]) [1,2,2,4] console.log(newArr)
flatMap()
只能展开一层数组
var arr = [1, 2]
const newArr = arr.flatMap(el => [[el, el * 2]])
// [[1,2],[2,4]]
console.log(newArr)
includes()
判断一个数组是否包含一个指定的值,如果包含则返回true
,否则返回false
。使用 includes()
比较字符串和字符时是区分大小写的。
Array.includes()
参数语法:
-
第一个参数:需要查找的元素值。
-
第二个参数:表示搜索的起始位置,默认为
0
。const obj = { id: 1 } var arr = [obj, { id: 2 }] // true console.log(arr.includes(obj))
传入第二个参数
console.log([1, 2, 3].includes(3)); // true
console.log([1, 2, 3].includes(3, 3)) // false
console.log([1, 2, 3].includes(3, 2)) // true
五、排序方法
sort()
对数组的元素进行排序,并返回排序后的原数组。
Array.sort()
参数语法:
- 第一个参数(可选):用来指定按某种顺序进行排列的函数。如果省略,元素按照转换为的字符串的各个字符串的
ASCII
码进行排序。该函数接收二个参数:
first
second
第一个用于比较的元素
第二个用于比较的元素
// Array的sort()方法默认把所有元素先转换为String再排序,结果'10'排在了'2'的前面,因为字符'1'比字符'2'的ASCII码小。
const arr = [10, 20, 1, 2].sort()
//[1, 10, 2, 20]
console.log(arr);
可以接收一个比较函数作为参数,实现自定义的排序。该函数接收两个参数,如果第一个参数应该位于第二个之前则返回一个负数
,如果两个参数相等返回0
,如果第一个参数应该位于第二个之后则返回一个正数
。
const arr = [10, 20, 1, 2]
arr.sort((value1, value2) => {
if (value1 < value2) {
return -1
}
if (value1 > value2) {
return 1
}
return 0
})
// [1, 2, 10, 20]
console.log(arr)
reverse()
将数组中元素的反转,并返回该数组。该方法会改变原数组。
const values = [1, 2, 3, 4, 5]
values.reverse()
//[5, 4, 3, 2, 1]
console.log(values)
六、 转换方法
toLocaleString()
toLocaleString()
返回一个字符串表示数组中的元素。数组中的元素将使用各自的 toLocaleString
方法转成字符串,这些字符串将使用一个特定语言环境的字符串,并用逗号隔开。
const array1 = [1, 'a', { id: 1 }, new Date()]
// 1,a,[object Object],2020/1/15 上午7:50:38
console.log(array1.toLocaleString())
toString()
返回一个由逗号连接起来的字符串。
const array1 = [1, 'abc', { id: 1 }]
// 1,abc,[object Object]
console.log(array1.toString())
join()
将一个数组的所有元素连接成一个字符串并返回这个字符串。如果数组只有一个元素,那么将返回该元素,而不使用分隔符。
Array.join()
参数语法:
-
第一个参数(可选):指定一个字符串来分隔数组的每个元素。如果不传,默认数组元素用逗号(
,
)分隔。如果是空字符串(""),则所有元素之间都没有任何字符。const arr = [1, 2, 3] // 1,2,3 console.log(arr.join()) // 123 console.log(arr.join('')) // 1+2+3 console.log(arr.join('+'))
七、 归并方法(迭代数组的所有项,然后构建一个最终返回的值)
reduce()
reduce()
方法从数组的第一项开始,迭代数组的所有元素,构建一个最终返回的值,返回函数累计处理的结果。
Array.reduce()
参数语法:
- 第一个参数(必填):
callback
执行数组中每个值的函数。该函数接收四个参数:
prev
cur
index
array
初始值, 或者上一次调用回调函数返回的值(必填)
当前元素值 (必填)
当前元素的索引值(可选)
数组对象本身(可选)
这个函数返回的任何值都会作为第一个参数自动传给下一项。
-
第二个参数(可选):
initialValue
作为第一次调用callback
函数时的第一个参数的值。如果没有提供初始值,则将使用数组中的第一个元素。在没有初始值的空数组上调用reduce
将报错。//Uncaught TypeError: Reduce of empty array with no initial value [].reduce(() => {}) const arr = ['L', 'O', 'V', 'E'].reduce((prev, cur) => { console.log('prev: ', prev) console.log('cur: ', cur) return prev + cur }) // LOVE console.log(arr)
第一次执行回调函数,prev 是 L,cur 是 O。第二次,prev 是 LO,cur 是 V(数组的第三项)。这个过程会持续到把数组中的每一项都访问一遍,最后返回结果LOVE。
reduceRight()
reduceRight()
和reduce()
作用类似,使用reduce()
还是reduceRight()
,主要取决于要从哪头开始遍历数组。除此之外,它们完全相同。
var values = [1,2,3,4,5]
var sum = values.reduceRight(function(prev, cur, index, array){
return prev + cur
});
//15
alert(sum)
第一次执行回调函数,prev 是 5,cur 是 4。第二次,prev 是 9(5 加 4 的结果),cur 是 3(数组的第三项)。这个过程会持续到把数组中的每一项都访问一遍,最后返回结果。
八、demo
实现由短划线分隔的单词变成骆驼式的
camelize("background-color") === 'backgroundColor'
function camelize(str) {
return str
.split('-') // my-long-word -> ['my', 'long', 'word']
.map(
(word, index) => index == 0 ? word : word[0].toUpperCase() + word.slice(1)
) // ['my', 'long', 'word'] -> ['my', 'Long', 'Word']
.join(''); // ['my', 'Long', 'Word'] -> myLongWord
}
数组去重
function unique(arr) {
let result = [];
for (let str of arr) {
if (!result.includes(str)) {
result.push(str)
}
}
return result
}
在已有的数组上创建一个对象,id
作为键,数组的每一项作为值。
let users = [
{ id: '111', name: "zhangsan", age: 20 },
{ id: '222', name: "lisi", age: 24 },
{ id: '333', name: "wangwu", age: 31 },
]
function groupById(array) {
return array.reduce((obj, value) => {
obj[value.id] = value
return obj
}, {})
}
/*
{
111: { id: "111", name: "zhangsan", age: 20 },
222: { id: "222", name: "lisi", age: 24 },
333: { id: "333", name: "wangwu", age: 31 }
}
*/
console.log(groupById(users))
参考链接
10 JavaScript array methods you should know
来自山东济南的用户 15天前
赞一个
来自北京朝阳的用户 15天前
,明明可以靠脸吃饭,可是你偏要靠才华,鼓励师都被你撩了我们怎么办
大神 听说你又有才 人又帅
来自重庆万州的用户 15天前
老哥,写得很不错
来自辽宁沈阳的用户 23天前
你们送过来的程序员已经见到了,挺厉害一小伙。另外我这边还缺个产品经理,什么时候给我送个过来?
来自上海徐汇的用户 27天前
太秀了老哥,顶一个
来自北京昌平的用户 28天前
学习开始
来自山东济南的用户 30天前
比我还好 一年的数据库 一年的后端 一点的前端 现在搞得什么都没有学号学精