一文详解JavaScript中的数组
前言
最近在重学JS基础,然后正好学到数组这,前期是通过看视频学习的,后来发现通过看视频学习进度实在是太慢了,所以又开始看书看文档学,然后就开始看“红宝书”(JavaScript高级程序设计)学习,看的最新的第四版的,数组这部分前期看视频学了一部分,后面又看书学了,前前后后学了有大概5天,当然是下班时间学习,学完了想写个全面的总结,然后就有了这篇文章,希望大佬们看了发现什么错误能在评论区指出,我会立马改正的。
1.数组介绍
(1)什么是数组?
数组是使用单独的变量名来存储一系列的值的一个对象。
(2)怎么创建数组?
创建数组有两种方式
- 对象方式创建数组
- 字面量方式创建数组
创建数组可以通过上面这两种方式,当然也可以通过Array.of()这个函数创建数组。
对象方式创建数组
let array = new Array();
Tips:
也可以通过下面这种方式创建数组对象
let array = Array();
这种方式创建数组,对象也可以通过这两种方式创建,那么这种方式与上面那种方式有什么区别呢,这两种方式创建数组的区别就是内部this指向不同,一个指向调用者,一个指向全局的window对象。
console.log(new Array(1)); // [empty]
console.log(new Array(1,2,3)); // [1, 2, 3]
console.log(Array.of(1)); // [1]
console.log(Array.of(1,2,3)); // [1, 2, 3]
Tips:
第一行代码是创建了一个长度为1的数组,因为没有值,这个位置会默认被undefined填充,也就是说打印结果 [empty] => [undefined]
字面量的方式创建数组
let arr = [];
这种方式创建数组非常的简单便捷,所以推荐使用这种方法创建数组
Tips:
使用字面量的方式创建数组不会调用Array构造函数
2.Array对象介绍
(1)Array介绍
上面我们也用了一个Array的方法,就是Array.of(),那么Array跟数组到底是什么关系呢,根据MDN上的定义:
JavaScript的 Array 对象是用于构造数组的全局对象,数组是类似于列表的高阶对象。
换句话说就是:
Array对象是js内置的用于构造数组的全局对象,数组身上的方法都是继承于Array对象。
我们来打印看下这个Array对象的结构:
我们从这个打印结果可以看出Array下面主要有三个 私有 方法:
方法名称 | 方法介绍 | JavaScript 版本 | 是否会改变原数组实例 |
---|---|---|---|
from() | 将类数组结构转换为数组实例 | ES6 | × |
isArray() | 判断数组是否为数组类型 | ES6 | × |
of() | 将一组参数转换为数组实例 | ES6 | × |
(2)Array.from()
参数 | 描述 |
---|---|
object | 必需,要转换为数组的对象 |
mapFunction | 可选,数组中每个元素要调用的函数 |
thisValue | 可选,映射函数(mapFunction)中的 this 对象 |
返回值 |
---|
新的数组实例 |
// 1.类数组对象
let obj = {
1: 'techerM',
2: 15,
length: 2
};
console.log(Array.from(obj)); // ["techerM", 15]
// 2.字符串
let str = '阿星';
console.log(Array.from(str)); // ["阿", "星"]
// 3.集合
let s = new Set().add(1)
.add(2)
.add(1)
.add(4);
console.log(Array.from(s)); // [1, 2, 4]
// 4.第二个参数,可操作数组中的每个元素
let numbersObj = {
0:1,
1:2,
2:3,
3:2,
length: 3
};
console.log(Array.from(numbersObj,item => item*3));//[3, 6, 9]
console.log(numbersObj); // {0: 1, 1: 2, 2: 3, 3: 2, length: 3}
// 5.第三个参数,指定第二个参数(函数)中this的指向
let numArray = [1,2,3];
var name = '小花';
let res1 = Array.from(numArray,function(item){
return this.name;
})
let res2 = Array.from(numArray,function(item){
return this.name;
},{name:'小丽'})
console.log(res1); // ["小花", "小花", "小花"]
console.log(res2); // ["小丽", "小丽", "小丽"]
Tips:
1.Array.from()是Array对象的私有方法,并不是Array原型prototype下的方法,所以数组继承不到这个方法,数组是没有这个方法的。
2.Array.from()第一个参数类数组对象的条件为:存在length属性,数据为可索引结构,例如下面这个对象就不可进行迭代,因为没有可索引结构
let obj = {
name: '小丽',
value: 100,
length: 2
}
3.Array.from()方法不会改变原数组
4.Array.from()中第3个参数设置第二个参数(函数)this的指向,不适用于箭头函数,也就是说如果你第二个参数用的箭头函数的写法,那么你设置第3个参数时将不起作用
Array.from()方法用于哪些地方
- 将字符串转换为数组
- 将集合和映射转换为数组
- 可以对现有数组进行浅复制
- 可应用于任何符合条件(length和索引)的可迭代对象
(3)Array.of()
参数 | 描述 |
---|---|
elementN | 任意个参数,将按顺序成为返回数组中的元素。 |
返回值 |
---|
新的数组实例 |
// 一组参数
console.log(Array.of(1,2,3)); // [1, 2, 3]
// 通过 Array.of() 创建数组对象
let arr = Array.of(1);
console.log(arr); // [1]
// new Array() 创建数组对象
let arr1 = new Array(1);
console.log(arr1); // [empty]
Tips:
通过Array.of()创建对象的方式弥补了通过 new Array 创建对象传一个参数创建对象的缺陷。
(4)Array.isArray()
参数 | 描述 |
---|---|
obj | 必需,要判断的对象。 |
返回值 |
---|
布尔值,如果对象是数组返回 true,否则返回 false。 |
let colors = ['red','green'];
let name = '小王';
let age = 18;
console.log(Array.isArray(colors)); // true
console.log(Array.isArray(name)); // false
console.log(Array.isArray(age)); // false
3.检测数组
一般我们在js中检测数据类型通常用 typeof 关键字,但是 typeof 并不能分开对象与数组,检测数组时返回的也是 object,所以我们就需要用其它的办法来区分对象与数组了。
方法 | 描述 |
---|---|
Array.isArray() | 返回一个布尔类型的值,是数组则返回true,反之false |
instanceof | 返回一个布尔类型的值,是数组则返回true,反之false |
Object.prototype.toString.call() | 返回详细的具体类型 |
let array = [1,2];
let obj = {name: '小明'};
console.log(Array.isArray(array)); // true
console.log(Array.isArray(obj)); // false
console.log(array instanceof Array); // true
console.log(obj instanceof Array); // false
console.log(Object.prototype.toString.call(array)); // [object Array]
console.log(Object.prototype.toString.call(obj)); // [object Object]
上面这个三个方法都可以用来区分对象和数组,平常我们使用还是最好使用 Array.isArray() 这个方法。
Tips:
通常我们使用instanceof是假定只有一个全局上下文,如果在多个框架页面中检测数组可能会有问题,因为我们并不能保证所有框架里的Array构造函数相同,所以最好使用Array.isArray() 这个方法判断。
4.数组中的方法
数组中的方法总览
首先我们从控制台打印看一下数组:
console.log([]);
从上图中我们可以看到数组中有32个方法,全部是挂在数组原型 _proto_ 上的,然后下面我们就来看一下这些数组方法。
方法 | 描述 | 是否改变原数组实例 |
---|---|---|
push() | 向数组的末尾添加一个或多个元素,并返回新的长度 | √ |
pop() | 删除并返回数组的最后一个元素 | √ |
unshift() | 向数组的开头添加一个或更多元素,并返回新的长度 | √ |
shift() | 把数组的第一个元素从其中删除,并返回第一个元素的值 | √ |
copyWithin() | 浅复制数组的一部分到同一数组中的另一个位置,并返回它,不会改变原数组的长度 | √ |
fill() | 向一个已有的数组中插入全部或部分相同的值 | √ |
reverse() | 用于颠倒数组中元素的顺序 | √ |
sort() | 用原地算法对数组的元素进行排序,并返回数组 | √ |
splice() | 向/从数组中添加/删除项目,然后返回被删除的项目 | √ |
slice() | 可提取字符串的某个部分,并以新的字符串返回被提取的部分 | × |
concat() | 用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组 | × |
join() | 将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串 | × |
every() | 对数组中每一项都运行传入的函数,如果对每一项函数都返回true,则这个方法返回true | × |
some() | 对数组中每一项都运行传入的函数,如果有一项函数返回true,则这个方法返回true | × |
filter() | 对数组每一项都运行传入的函数,函数返回true的项会组成数组之后返回 | × |
map() | 对数组每一项都运行传入的函数,返回由每次函数调用的结果构成的数组 | × |
forEach() | 对数组每一项都运行传入的函数,没有返回值 | × |
keys() | 返回数组索引的迭代器 | × |
values() | 返回数组元素的迭代器 | × |
entries() | 返回 索引/值 对的迭代器 | × |
reduce() | 对数组中的每个元素执行一个由您提供的reducer函数,将其结果汇总为单个返回值 | × |
reduceRight() | 从数组的末尾向前将数组中的数组项做累加 | × |
indexOf() | 返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1 | × |
lastIndexOf() | 返回查找元素在数组中的位置,从数组末尾开始向前查找 | × |
includes() | 用来判断一个数组是否包含一个指定的值,如果包含则返回 true,否则返回false | × |
find() | 返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined | × |
findIndex() | 返回数组中满足提供的测试函数的第一个元素的索引。若没有找到对应元素则返回-1 | × |
toSting() | 返回由数组中每个值的等效字符串拼接而成的一个用逗号分隔的字符串 | × |
toLocaleString() | 返回一个逗号分隔的数组值的字符串 | × |
constructor() | 返回数组函数的引用,也就是调用这个方法的数组本身 | × |
flat() | 会按照一个可指定的深度递归遍历数组,将所有元素与遍历到的子数组中的元素合并为一个新数组返回 | × |
flatMap() | 使用映射函数映射每个元素,然后将结果压缩成一个新数组 | × |
上面是数组中的所有方法,然后下面我们分10类来介绍这些方法。
- 栈和队列方法(4个)
- 复制和填充方法(2个)
- 排序方法(2个)
- 操作方法(4个)
- 迭代方法(5个)
- 迭代器方法(3个)
- 归并方法(2个)
- 搜索查找方法(5个)
- 转换方法(2个)
- 扁平化方法(2个)
(1)栈和队列方法
栈是一种后进先出的数据结构,也就是最新添加的项先被删除。数据项的插入(称为推入,push)和删除(称为弹出,pop)只在栈的一个地方发生,即栈顶。js为数组提供了push() 和 pop() 方法,以实现类似栈的行为。
push()
方法 | 描述 | 返回值 |
---|---|---|
push() | 向数组的末尾添加一个或多个元素 | 把指定的值添加到数组后的新长度 |
参数 | 描述 |
---|---|
newelement1 | 必需。要添加到数组的第一个元素 |
newelement2 | 可选。要添加到数组的第二个元素 |
newelementX | 可选。可添加多个元素 |
let arr = ['js','css','html'];
console.log(arr.push('go','node.js')); // 5
console.log(arr); // ["js", "css", "html", "go", "node.js"]
let arr1 = ['js','css','html'];
let array = ['go','node.js'];
console.log(arr1.push(...array)); // 5
console.log(arr1); // ["js", "css", "html", "go", "node.js"]
小知识点:
我们也可以通过 array[array.length] = 'XXX' 这种方式往数组后面添加元素
let arr = ['js','css','html'];
arr[arr.length] = 'go';
console.log(arr); // ["js", "css", "html", "go"]
pop()
方法 | 描述 | 返回值 |
---|---|---|
pop() | 删除并返回数组的最后一个元素 | 返回被删除的元素 |
参数 | 描述 |
---|---|
无需传参 | 无需描述 |
let colors = ['red','green','blue']
console.log(colors.pop()); // blue
console.log(colors); // ["red", "green"]
小知识点:
我们也可以通过 array.length = array.length - 1 这种方式从数组末尾删除元素
let colors = ['red','green','blue'];
colors.length = colors.length - 1;
console.log(colors); // ["red", "green"]
Tips:
push()和pop()一起使用就构成了后进先出的栈结构
let array = [];
console.log(array.push('red','green')); // 2
console.log(array); // ["red", "green"]
console.log(array.pop()); // green
console.log(array); // ["red"]
unshift()
方法 | 描述 | 返回值 |
---|---|---|
unshift() | 向数组的开头添加一个或更多元素 | 把指定的值添加到数组后的新长度 |
参数 | 描述 |
---|---|
newelement1 | 必需。向数组添加的第一个元素 |
newelement2 | 可选。向数组添加的第二个元素 |
newelementX | 可选。可添加若干个元素 |
let colors = ['white'];
console.log(colors.unshift('red','blue')); // 3
console.log(colors); // ["red", "blue", "white"]
shift()
方法 | 描述 | 返回值 |
---|---|---|
shift() | 把数组的第一个元素从其中删除 | 返回第一个元素的值 |
参数 | 描述 |
---|---|
无需传参 | 无需描述 |
let colors = ['red','black'];
console.log(colors.shift()); // red
console.log(colors); // ["black"]
Tips:
unshift()和shift()一起使用也构成了后进先出的栈结构
unshift()和pop()一起使用构成了先进先出的队列结构
push()和shift()一起使用也构成了先进先出的队列结构
(2)复制和填充方法
ES6新增了两个方法:批量复制方法 copyWithin(),以及填充数组方法 fill()。使用这两个方法都不会改变数组的大小。同时这两个方法都是包含开始索引,不包含结束索引的。
copyWithin()
方法 | 描述 | 返回值 |
---|---|---|
copyWithin() | 浅复制数组的一部分到同一数组中的另一个位置 | 返回修改后的原数组 |
参数 | 描述 |
---|---|
target | 必需。复制到指定目标索引位置 |
start | 可选。元素复制的起始位置 |
end | 可选。停止复制的索引位置 (默认为 array.length)。如果为负值,表示倒数 |
let ints = [0,1,2];
let copyRes = ints.copyWithin(1);
console.log(copyRes); // [0, 0, 1]
console.log(ints); // [0, 0, 1]
console.log(copyRes === ints); // true
fill()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
fill() | 向一个已有的数组中插入全部或部分相同的值 | 返回填充后的原数组 | √ |
参数 | 描述 |
---|---|
value | 必需。填充的值 |
start | 可选。开始填充位置 |
end | 可选。停止填充位置 (默认为 array.length) |
let zeroes = [0,0,0,0,0];
let zeroesRes = zeroes.fill(5);
console.log(zeroes); // [5, 5, 5, 5, 5]
console.log(zeroesRes === zeroes); // true
console.log(zeroes.fill(3,1)); // [5, 3, 3, 3, 3]
console.log(zeroes); // [5, 3, 3, 3, 3]
console.log(zeroes.fill(1,3,5)); // [5, 3, 3, 1, 1]
console.log(zeroes); // [5, 3, 3, 1, 1]
Tips:
copyWithin()和fill()会忽略超出数组边界,零长度以及方向相反的索引范围
let ints = [0,1,2,3];
// 索引超出边界,忽略
ints.copyWithin(1,10,13);
console.log(ints); // [0,1,2,3]
// 索引过低,超出边界,忽略
ints.copyWithin(2,-15,-12);
console.log(ints); // [0,1,2,3]
// 索引反向,忽略
ints.copyWithin(1,3,1);
console.log(ints); // [0,1,2,3]
// 部分索引可用,填充可用索引部分
ints.copyWithin(1,2,6);
console.log(ints); // [0,2,3,3]
let zeroes = [0,0,0,0,0];
// 当开始索引和结束索引取负值时,相当于:将开始索引和结束索引都加上 zeroes.length
// zeroes.fill(8,1,4);
zeroes.fill(8,-4,-1);
console.log(zeroes); // [0,8,8,8,0]
// 索引超出边界,忽略
zeroes.fill(1,10,15);
console.log(zeroes); // [0,8,8,8,0]
// 索引过低,超出边界,忽略
zeroes.fill(1,-15,-12);
console.log(zeroes); // [0,8,8,8,0]
// 索引反向,忽略
zeroes.fill(1,3,1);
console.log(zeroes); // [0,8,8,8,0]
// 部分索引可用,填充可用索引部分
zeroes.fill(1,3,10);
console.log(zeroes); // [0, 8, 8, 1, 1]
(3)排序方法
数组中有两个方法可以用来对元素重新排序:reverse() 和 sort(),顾名思义,reverse()方法就是将数组元素反向排列。
reverse()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
reverse() | 用于颠倒数组中元素的顺序 | 返回颠倒后的原数组 | √ |
参数 | 描述 |
---|---|
无需参数 | 无需描述 |
let value = [1,2,3,4,5,6];
console.log(value.reverse()); // [6, 5, 4, 3, 2, 1]
console.log(value); // [6, 5, 4, 3, 2, 1]
console.log(value.reverse() === value); // true
sort()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
sort() | 用原地算法对数组的元素进行排序 | 返回排序后的原数组 | √ |
参数 | 描述 |
---|---|
sortby | 可选。规定排序顺序。必须是函数 |
- 当不传参数时
默认情况下,sort() 会按照升序重新排列数组元素,既最小的值在前面,最大的值在后面。为此,sort() 会在每一项上调用String() 转型函数,然后比较字符串来决定顺序。即使数组的元素都是数值,也会把数组转换为字符串再比较排序。
let value = [1,2,3,5,8,9,10,16,20,50];
console.log(value.sort()); // [1, 10, 16, 2, 20, 3, 5, 50, 8, 9]
- 传入比较函数
这时候排序的结果就是我们结果就是我们想要的
let value = [1,2,3,5,8,9,10,16,20,50];
function compare(a,b) {
if(a < b) return -1
else if(a > b) return 1
else return 0;
}
value.sort(compare);
console.log(value); // [1, 2, 3, 5, 8, 9, 10, 16, 20, 50]
当想要结果按降序排列的话将if条件反过来即可
let value = [1,2,3,5,8,9,10,16,20,50];
function compare(a,b) {
if(a > b) return -1
else if(a < b) return 1
else return 0;
}
value.sort(compare);
console.log(value); // [50, 20, 16, 10, 9, 8, 5, 3, 2, 1]
上面的代码也可简写为:
let value = [1,2,3,5,8,9,10,16,20,50];
value.sort((a,b) => a > b ? -1 : a > b ? 1 : 0);
console.log(value); // [50, 20, 16, 10, 9, 8, 5, 3, 2, 1]
上面的代码还可简写为:
let value = [1,2,3,5,8,9,10,16,20,50];
value.sort((a,b) => b - a); // a - b 升序,b - a 降序
console.log(value); // [50, 20, 16, 10, 9, 8, 5, 3, 2, 1]
- 数组对象按某个属性排序
let array = [
{'name':'js','grade':80},
{'name':'java','grade':50},
{'name':'go','grade':100},
]
array.sort(function(a,b) {
return b.grade - a.grade;
})
console.log(array);
// [{'name':'go','grade':100},{'name':'js','grade':80},{'name':'java','grade':50}]
- 手写一个sort函数
function sort(array,callback) {
for (const n in array) {
for (const m in array) {
if(callback(array[n],array[m]) < 0){
const temp = array[n];
array[n] = array[m];
array[m] = temp;
}
}
}
return array;
};
let arr = [10,52,2,3,7];
sort(arr,function(a,b){
return a - b
})
console.log(arr); // [2, 3, 7, 10, 52]
Tips:
如果只是想反转数组的顺序,reverse()更简单也更快。
(4)操作方法
对于数组中的元素,我们有很多操作方法。
splice()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
splice() | 向/从数组中添加/删除项目 | 返回被删除元素的组成的数组 | √ |
参数 | 描述 |
---|---|
index | 必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置 |
howmany | 必需。要删除的项目数量。如果设置为 0,则不会删除项目 |
index | 可选。向数组添加的新项目 |
let nums = [1,2,3,4,5,6,7,8,9,10];
console.log(nums.splice(0,2)); // [1, 2]
console.log(nums); // [3, 4, 5, 6, 7, 8, 9, 10]
let colors = ['red','green'];
console.log(colors.splice(0,1,'black','white')); // ["red"]
console.log(colors); // ["black", "white", "green"]
Tips:
如果splice() 不传参数时,不会删除任何元素,返回一个空数组,当传一个参数时,从当前下标对应的元素(包含当前下标对应的元素)往后删除,返回被删除元素的组成的数组
let nums = [1,2,3,4,5,6,7,8,9,10];
console.log(nums.splice()); // []
console.log(nums); // [1,2,3,4,5,6,7,8,9,10]
console.log(nums.splice(3)); // [4, 5, 6, 7, 8, 9, 10]
console.log(nums); // [1, 2, 3]
slice()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
slice() | 可提取字符串的某个部分 | 以新数组的形式返回被提取的部分 | × |
参数 | 描述 |
---|---|
start | 可选。规定从何处开始选取,包含这个位置 |
end | 可选。规定从何处结束选取,不包含这个位置 |
let colors = ['red','blue'];
let colors2 = colors.slice();
let colors3 = colors.slice(1);
let colors4 = colors.slice(0,1);
console.log(colors); // ["red", "blue"]
console.log(colors2); // ["red", "blue"]
console.log(colors3); // ["blue"]
console.log(colors4); // ["red"]
Tips:
如果slice() 的参数有负值,那么就以当前数组长度加上这个负值的结果确定位置。当数组长度加上这个负值仍然为负值,那么返回空数组。
let colors = ['red','blue','green'];
// 这个数组的长度为3,所以colors.slice(-3,-1) 相当于 colors.slice(0,2)
console.log(colors.slice(-3,-1)); // ["red", "blue"]
console.log(colors.slice(0,2)); // ["red", "blue"]
// 因为colors.slice(-6,-4) 加上数组长度分别为 -3,-1,所以返回空值
// 但是colors.slice(-6,-4) 结果并不等于 colors.slice(-3,-1)的结果
// 因为 colors.slice(-3,-1) 相当于 colors.slice(0,2)
console.log(colors.slice(-6,-4)); // []
console.log(colors.slice(-3,-1)); // ["red", "blue"]
// colors.slice(-8,-1) 加上数组长度分别为 -5,2,有一部分是在数组索引范围内的
// 所以这部分是生效的
console.log(colors.slice(-8,-1)); // ["red", "blue"]
// colors.slice(-5,2) 加上数组长度为 -2,2
// 但是 colors.slice(-2,2) 加上数组长度为 1,2
// 所以他们结果是不同的
console.log(colors.slice(-5,2)); // ["red", "blue"]
console.log(colors.slice(-2,2)); // ["blue"]
concat()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
concat() | 用于合并两个或多个数组 | 返回合并后的新创建的数组 | × |
参数 | 描述 |
---|---|
arrayX | 必需。该参数可以是具体的值,也可以是数组对象。可以是任意多个 |
concat不仅可以合并数组,也可以将字符串合并到数组中去
let colors = ['red','green'];
let newColors = ['brown','blue'];
console.log(colors.concat(newColors)); // ["red", "green", "brown", "blue"]
console.log(colors.concat(['yellow'],newColors)); // ["red", "green", "yellow", "brown", "blue"]
console.log(colors.concat('white',newColors)); // ["red", "green", "white", "brown", "blue"]
Tips:
concat() 将字符串合并到数组中有点类似于push() ,但是concat() 不会改变原数组,而push() 会改变原数组,同时,concat() 的返回值是合并后的新数组,而push() 的返回值是添加元素后的原数组的长度
let colors = ['red'];
console.log(colors.concat('green','blue')); // ["red", "green", "blue"]
console.log(colors); // ["red"]
let newColors = ['red'];
console.log(colors.push('green','blue')); // 3
console.log(colors); // ["red", "green", "blue"]
join()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
join() | 将一个数组的所有元素连接成一个字符串并返回 | 返回连接后的字符串 | × |
参数 | 描述 |
---|---|
separator | 可选。指定要使用的分隔符。如果省略该参数,则使用逗号作为分隔符 |
let colors = ['red','green','blue'];
console.log(colors.join()); // red,green,blue
console.log(colors.join(',')); // red,green,blue
console.log(colors.join('||')); // red||green||blue
console.log(colors.join(undefined)); // red,green,blue
console.log(colors.join(null)); // rednullgreennullblue
Tips:
当不给join() 传入任何参数,或者传入undefined ,则仍然使用逗号作为分隔符。如果数组中某一项是null 或undefined ,则在join() 返回的结果中会以空字符串表示。
let colors = ['red','green','blue'];
console.log(colors.join(undefined)); // red,green,blue
let colors1 = ['red',null,undefined,'blue'];
console.log(colors1.join()); // red,,,blue
(5)迭代方法
JavaScript 为数组定义了5个迭代方法。
every()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
every() | 对数组中每一项都运行传入的函数,如果对 每一项 函数都返回 true ,则这个方法返回 true | 返回一个布尔类型的值 | × |
参数 | 描述 |
---|---|
function(currentValue, index,arr) | 必须。函数,数组中的每个元素都会执行这个函数 |
thisValue | 可选。对象作为该执行回调时使用,传递给函数,用作 "this" 的值 |
第一个参数(函数)的参数:
参数 | 描述 |
---|---|
currentValue | 必须。当前元素的值 |
index | 可选。当前元素的索引值 |
arr | 可选。当前元素属于的数组对象 |
let numbers = [1,2,3,4,5,4,3,2,1];
let everyResult = numbers.every((item,index,numbers) => item > 2);
console.log(everyResult); // false
Tips:
若收到一个空数组,此方法在一切情况下都会返回 true
let numbers = [];
let everyResult = numbers.every((item,index,numbers) => item > 5);
console.log(everyResult); // true
some()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
some() | 对数组中每一项都运行传入的函数,如果 有一项 函数返回 true ,则这个方法返回 true | 返回一个布尔类型的值 | × |
参数 | 描述 |
---|---|
function(currentValue, index,arr) | 必须。函数,数组中的每个元素都会执行这个函数 |
thisValue | 可选。对象作为该执行回调时使用,传递给函数,用作 "this" 的值 |
第一个参数(函数)的参数:
参数 | 描述 |
---|---|
currentValue | 必须。当前元素的值 |
index | 可选。当前元素的索引值 |
arr | 可选。当前元素属于的数组对象 |
注: every() 和 some() 接收的参数是一样的,只是 every() 需要函数 每一项 都返回 true ,这个方法才会返回 true ,而 some() 只需要函数 某一项 返回 true ,这个方法就会返回 true 。
let numbers = [1,2,3,4,5,4,3,2,1];
let everyResult = numbers.every((item,index,numbers) => item > 2);
console.log(everyResult); // false
let someResult = numbers.some((item,index,numbers) => item > 2);
console.log(someResult); // true
filter()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
filter() | 对数组每一项都运行传入的函数,函数返回 true 的项会组成数组之后返回 | 返回一个数组 | × |
参数 | 描述 |
---|---|
function(currentValue, index,arr) | 必须。函数,数组中的每个元素都会执行这个函数 |
thisValue | 可选。对象作为该执行回调时使用,传递给函数,用作 "this" 的值 |
第一个参数(函数)的参数:
参数 | 描述 |
---|---|
currentValue | 必须。当前元素的值 |
index | 可选。当前元素的索引值 |
arr | 可选。当前元素属于的数组对象 |
let numbers = [1,2,3,4,5,4,3,2,1];
let filterResult = numbers.filter((item,index,numbers) => item > 2);
console.log(filterResult); // [3, 4, 5, 4, 3]
map()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
map() | 对数组每一项都运行传入的函数,返回由每次函数调用的结果构成的数组 | 返回一个数组 | × |
参数 | 描述 |
---|---|
function(currentValue, index,arr) | 必须。函数,数组中的每个元素都会执行这个函数 |
thisValue | 可选。对象作为该执行回调时使用,传递给函数,用作 "this" 的值 |
第一个参数(函数)的参数:
参数 | 描述 |
---|---|
currentValue | 必须。当前元素的值 |
index | 可选。当前元素的索引值 |
arr | 可选。当前元素属于的数组对象 |
let numbers = [1,2,3,4,5,4,3,2,1];
let mapResult = numbers.map((item,index,number) => item*2);
console.log(mapResult); // [2, 4, 6, 8, 10, 8, 6, 4, 2]
Tips:
从上面的代码以及描述看,fliter() 和 map() 好像没什么区别,事实上,这两个方法还是有区别的,fliter() 返回的数组元素个数可能会变化,但是元素本省不会变化,也就是说 fliter() 返回的新数组一定是跟原数组一样的内容或者原数组内容的一部分,元素不会改变,而 map() 返回的新数组元素个数不变,但是按照一定的条件转换,数组元素可能会变化
let numbers = [1,2,3,4,5,4,3,2,1];
let filterResult = numbers.filter((item,index,number) => item * 2);
let mapResult = numbers.map((item,index,number) => item * 2);
let filterResult1 = numbers.filter((item,index,number) => item > 2);
let mapResult1 = numbers.map((item,index,number) => item > 2);
console.log(filterResult); // [1, 2, 3, 4, 5, 4, 3, 2, 1]
console.log(mapResult); // [2, 4, 6, 8, 10, 8, 6, 4, 2]
console.log(filterResult1); // [3, 4, 5, 4, 3]
console.log(mapResult1); // [false, false, true, true, true, true, true, false, false]
console.log(numbers); // [1, 2, 3, 4, 5, 4, 3, 2, 1]
forEach()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
forEach() | 对数组每一项都运行传入的函数,没有返回值 | undefined | × |
参数 | 描述 |
---|---|
function(currentValue, index,arr) | 必须。函数,数组中的每个元素都会执行这个函数 |
thisValue | 可选。对象作为该执行回调时使用,传递给函数,用作 "this" 的值 |
第一个参数(函数)的参数:
参数 | 描述 |
---|---|
currentValue | 必须。当前元素的值 |
index | 可选。当前元素的索引值 |
arr | 可选。当前元素属于的数组对象 |
let numbers = [1,2,3,4,5,4,3,2,1];
let forEachResult = numbers.forEach((item,index,numbers) => {
return item*5
});
console.log(forEachResult); // undefined
console.log(numbers); // [1, 2, 3, 4, 5, 4, 3, 2, 1]
forEach()本质上就是循环遍历数组,没有返回值,也不会改变原数组。
总结
这5个迭代方法传的参数都是一样的,也都不会改变原数组。
(6)迭代器方法
在 ES6 中,Array 的原型上暴露了 3 个用于检索数组内容的方法,keys() 、values() 和 entries()。
keys()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
keys() | 返回数组索引的迭代器 | 返回一个类数组对象 | × |
参数 | 描述 |
---|---|
obj | 可选。要返回其枚举自身属性的对象 |
let colors = ['red','green'];
console.log(colors.keys()); // Array Iterator {}
console.log(Array.from(colors.keys())); // [0, 1]
console.log(Array.of(...colors.keys())); // [0, 1]
values()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
values() | 返回数组元素的迭代器 | 返回一个类数组对象 | × |
参数 | 描述 |
---|---|
obj | 可选。被返回可枚举属性值的对象 |
let colors = ['red','green'];
console.log(colors.values()); // Array Iterator {}
console.log(Array.from(colors.values())); // ["red", "green"]
console.log(Array.of(...colors.values())); // ["red", "green"]
entries()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
entries() | 返回 索引/值 对的迭代器 | 返回一个类数组对象 | × |
参数 | 描述 |
---|---|
obj | 可选。被返回可枚举属性值的对象 |
let colors = ['red','green'];
console.log(colors.entries(colors)); // Array Iterator {}
console.log(Array.from(colors.entries())); // [Array(2), Array(2)]
console.log(Array.of(...colors.entries())); // [Array(2), Array(2)]
Tips:
这三个方法返回的都是一个类数组对象,都可以通过 Array.from() 或者 Array.of()加展开语法 转换成数组。
(7)归并方法
JavaScript 为数组提供了两个归并方法:reduce() 和 reduceRight() 。
reduce()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
reduce() | 对数组中的每个元素执行一个由您提供的reducer函数 | 函数处理的结果,可以是任何类型 | × |
参数 | 描述 |
---|---|
function(currentValue, index,arr) | 必需。用于执行每个数组元素的函数 |
initialValue | 可选。传递给函数的初始值 |
第一个参数(函数)的参数:
参数 | 描述 |
---|---|
total | 必需。初始值, 或者计算结束后的返回值 |
currentValue | 必需。当前元素 |
currentIndex | 可选。当前元素的索引 |
arr | 可选。当前元素所属的数组对象 |
let numbers = [1,2,3,2,1];
let sum = numbers.reduce((prev,cur,index,array) => prev + cur);
console.log(sum); // 9
console.log(numbers); // [1, 2, 3, 2, 1]
reduceRight()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
reduceRight() | 从数组的末尾向前将数组中的数组项做累加 | 函数处理的结果,可以是任何类型 | × |
参数 | 描述 |
---|---|
function(currentValue, index,arr) | 必需。用于执行每个数组元素的函数 |
initialValue | 可选。传递给函数的初始值 |
第一个参数(函数)的参数:
参数 | 描述 |
---|---|
total | 必需。初始值, 或者计算结束后的返回值 |
currentValue | 必需。当前元素 |
currentIndex | 可选。当前元素的索引 |
arr | 可选。当前元素所属的数组对象 |
let numbers = [1,2,3,4,5];
let sum = numbers.reduceRight((prev,cur,index,array) => prev + cur);
console.log(sum); // 15
console.log(numbers); // [1, 2, 3, 4, 5]
Tips:
究竟是使用 reduce() 还是 reduceRight() ,只取决于遍历数组元素的方向。除此之外,这两个方法没什么区别。
(8)搜索查找方法
JavaScript 提供两类搜索数组的方法:按严格相等搜索和按断言函数搜索。
JavaScript 提供了 3 个严格相等的搜索方法:indexOf()、lastIndexOf() 和 includes()
indexOf()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
indexOf() | 返回在数组中可以找到一个给定元素的第一个索引 | 返回数值类型 | × |
参数 | 描述 |
---|---|
searchvalue | 必需。规定需检索的字符串值 |
fromindex | 可选的整数参数。规定在字符串中开始检索的位置(包含这个位置) |
let numbers = [1,2,3,4,5];
console.log(numbers.indexOf(4)); // 3
console.log(numbers.indexOf(4,3)); // 3
// 如果没找到就返回 -1
console.log(numbers.indexOf(40)); // -1
lastIndexOf()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
lastIndexOf() | 返回查找元素在数组中的位置,从数组末尾开始向前查找 | 返回数值类型 | × |
参数 | 描述 |
---|---|
searchvalue | 必需。规定需检索的字符串值 |
fromindex | 可选的整数参数。规定在字符串中开始检索的位置(包含这个位置) |
let numbers = [1,2,3,4,5,4,3,2,1];
console.log(numbers.lastIndexOf(4)); // 5
console.log(numbers.lastIndexOf(4,4)); // 3
// 如果没找到就返回 -1
console.log(numbers.lastIndexOf(40)); // -1
includes()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
includes() | 用来判断一个数组是否包含一个指定的值 | 返回布尔类型 | × |
参数 | 描述 |
---|---|
searchvalue | 必需。规定需检索的字符串值 |
fromindex | 可选的整数参数。规定在字符串中开始检索的位置(包含这个位置) |
let numbers = [1,2,3,4,5,4,3,2,1];
console.log(numbers.includes(4)); // true
console.log(numbers.includes(4,7)); // false
console.log(numbers.includes(40)); // false
JavaScript 也允许按照定义的断言函数搜索数组,find() 和 findIndex() 使用了断言函数。
find()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
find() | 返回数组中满足提供的测试函数的第一个元素的值 | 返回符合条件的元素值,可以是任何类型 | × |
参数 | 描述 |
---|---|
function(currentValue, index,arr) | 必须。函数,数组中的每个元素都会执行这个函数 |
thisValue | 可选。对象作为该执行回调时使用,传递给函数,用作 "this" 的值 |
第一个参数(函数)的参数:
参数 | 描述 |
---|---|
currentValue | 必须。当前元素的值 |
index | 可选。当前元素的索引值 |
arr | 可选。当前元素属于的数组对象 |
const people = [
{
name: 'Matt',
age: 27
},
{
name: 'xiaoming',
age: 29
}
];
console.log(people.find((element, index, array) => element.age > 28)); // {name: "xiaoming", age: 29}
findIndex()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
findIndex() | 返回数组中满足提供的测试函数的第一个元素的索引 | 返回一个数值类型的值 | × |
参数 | 描述 |
---|---|
function(currentValue, index,arr) | 必须。函数,数组中的每个元素都会执行这个函数 |
thisValue | 可选。对象作为该执行回调时使用,传递给函数,用作 "this" 的值 |
第一个参数(函数)的参数:
参数 | 描述 |
---|---|
currentValue | 必须。当前元素的值 |
index | 可选。当前元素的索引值 |
arr | 可选。当前元素属于的数组对象 |
const people = [
{
name: 'Matt',
age: 27
},
{
name: 'xiaoming',
age: 29
}
];
console.log(people.findIndex((element, index, array) => element.age > 28)); // 1
(9)转换方法
JavaScript 中所有对象都有 toSting()、toLocaleString() 和 valueOf() 方法,其中,valueOf() 返回的是数组本身。
toSting()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
toSting() | 返回由数组中每个值的等效字符串拼接而成的一个用逗号分隔的字符串 | 返回字符串类型 | × |
参数 | 描述 |
---|---|
无需参数 | 无需描述 |
let numbers = [1,2,3,4,5];
let stringNumbers = numbers.toString();
console.log(stringNumbers); // 1,2,3,4,5
toLocaleString()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
toLocaleString() | 返回一个逗号分隔的数组值的字符串 | 返回字符串类型 | × |
参数 | 描述 |
---|---|
无需参数 | 无需描述 |
let numbers = [15000000];
let stringNumbers = numbers.toLocaleString();
console.log(stringNumbers); // 15,000,000
(10)扁平化方法
JavaScript 中提供了两个数组扁平化的方法:flat() 和 flatMap()
flat()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
flat() | 会按照一个可指定的深度递归遍历数组,将所有元素与遍历到的子数组中的元素合并为一个新数组返回 | 返回一个数组类型 | × |
参数 | 描述 |
---|---|
depth | 可选。指定要提取嵌套数组的结构深度,默认值为 1 |
let array = [1,5,9,8,[1],[2,[1,[1,3,[1,9]]]]];
console.log(array.flat(2));// [1, 5, 9, 8, 1, 2, 1, Array(3)]
//使用 Infinity,可展开任意深度的嵌套数组
console.log(array.flat(Infinity)); // [1, 5, 9, 8, 1, 2, 1, 1, 3, 1, 9]
flatMap()
方法 | 描述 | 返回值 | 是否改变原数组实例 |
---|---|---|---|
flatMap() | 使用映射函数映射每个元素,然后将结果压缩成一个新数组 | 返回一个数组类型 | × |
参数 | 描述 |
---|---|
function(currentValue, index,arr) | 必须。函数,数组中的每个元素都会执行这个函数 |
thisValue | 可选。对象作为该执行回调时使用,传递给函数,用作 "this" 的值 |
第一个参数(函数)的参数:
参数 | 描述 |
---|---|
currentValue | 必须。当前元素的值 |
index | 可选。当前元素的索引值 |
arr | 可选。当前元素属于的数组对象 |
let array = [1,5,9,8];
let flatMapRes = array.flatMap((item,index,array) => item * 3);
console.log(flatMapRes); // [3, 15, 27, 24]
5.总结
这篇文章断断续续的也写了好几天,感叹总结文档也是件麻烦细致活,不比学习技术知识花的时间少,但是写文档也算把学到的知识输出出来了,可能以后自己忘了,也能回头来看看,毕竟,人的记忆力是敌不过时间的,好记性不如烂笔头嘛,写文档这种东西可能还是多多益善,然后大佬们看这篇文章如果发现有不妥或者错误的地方希望能指出来,我及时改正,谢谢了,然后后续有新的东西我也会补充进来的。