Array数组
Array
是JavaScript
中最常用的类型之一,数组是存储数据的有序列表,在JavaScript
中,数组中的每一项都可以保存任何数据类型的数据,也就是说,数组的第一项保存的可以是字符串,第二项可以保存数值,第三项可以保存对象,以此类推
对于操作数组,我们需要掌握其包含的一些方法,才能更好的去使用数组。JS中数组的方法种类众多,有的在ES5之前的版本就定义好了,有的是ES5、ES6中新增的方法,还有的是在Object
上继承的,接下来将介绍一些Array
常见的方法
数组
数组创建
字面量表示法
数组字面量是由一对包含数组项的方括号表示,多个数组项之间用逗号隔开
let arr1 = []; // 创建一个空数组
let arr2 = [3]; // 创建一个包含单项的数组
let arr3 = [1, 2, 3, 4]; // 创建一个包含4项的数组
Array构造函数
let arr1 = new Object(); // 创建一个新数组
let arr2 = new Object(5); // 创建一个长度为5,值为空的数组
let arr3 = new Object(1, 2, 3, 4); // 创建一个包含4项的数组
数组长度
ECMAScript
数组的大小是可以动态调整的,即可以随着数据的添加自动的增长以容纳新增数据
可以通过基于数组中从0开始的索引获取到该索引对应数组项的值,索引是基于0开始,而数组长度是数组项数的个数
let arr = [1 ,2 , 3, 4];
console.log(arr[0], arr[1], arr[2], arr[3]); // 1 2 3 4
console.log(arr,length); // 4
动态增删数组项
数组存在一个length
属性,它不是只读的,通过设置这个值,可以从数组末尾移除项和添加项
let color = ['red', 'green', 'blue']; // 创建一个包含3个字符的数组
console.log(arr.length); // 3
color.length = 2; // 将color数组的长度修改为2
console.log(color[2]); // undefined
在这个例子中的color数组一开始有3个值,将其数组的长度修改成2会移除最后一项(索引号为2)的值,再次访问color[2]的值会发现"blue"已经被移除了,结果变成undefined
了
let color = ["red", "green", "blue"];
color[length] = "black"; // 在索引为length处添加"black"
console.log(color.length); // 4
console.log(color[4]); // "black";
由于数组最后一项的索引始终为该数组的length-1
,因此下一个新项的位置就是length
,每当在数组中添加值时,length
就是自动改变以适应新的数组长度,我们可以通过这个方法很好的为数组的最后一项添加新值
数组方法
数组检测
instanceof
方法:对于在一个全局作用域中,使用instanceof
可以判断出某个对象是不是数组,改方法返回一个布尔值
if(arr instanceof Array) {
// 处理程序
}
如果网页中包含多个框架,即多个不同的执行环境,存在了多个不同版本的Array
构造函数,则instanceof
可能就是不是很适用了,在ECMAScript5
中新增了Arrar.isArray()
方法
Arrar.isArray()
方法:该方法的目的是最终确定某个值是不是数组,而不会管它是在那个全局执行环境建立的,返回一个布尔值结果
if(Array.isArray(value)) {
// 处理程序
}
栈方法
ECMAScript
数组也提供了一种让数组行为表现得像栈一样的方法
栈是一种LIFO(Last In First Out,后进先出)的数据结构,也就是最晚添加的项最早被移除,栈中项的插入和弹出只会发生在栈的顶部
为实现栈数据结构的实现方法,ECMAScript
提供了push()
和pop()
方法
push()
:该方法接受任意数量的参数,并将它们一个一个的添加到数组的末尾,并返回一个修改后数组长度的结果pop()
:该方法会将数组最后的一项移除,减少数组的length
长度,然后返回移除的项
let color = [];
let count = color.push("red", "blue");
console.log(color.length); // 2
console.log(count); // 2
let result = color.pop();
console.log(color.length); // 1
console.log(result); // "blue"
我们使用push()
方法将两个字符串推入color数组的末尾,并将返回的结果保存至count中(值为2),然后再次使用pop()
方法移除掉最后一项,然后将返回结果保存在result(值为"blue")
队列方法
队列也是一种数据结构,队列数据结构的访问形式为FIFO(First In First Out,先进先出),队列在列表的末端添加项,在前端移除项
在ECMAScript
中提供了shift()
和unshift()
方法
shift()
:移除数组中第一项的值,并将移除的值作为返回的结果,同时数组的长度-1unshift()
:在数组前端添加任意多个值,并返回新数组的长度
为了实现队列方法,我们可以组合使用push()
和shift()
方法,达成一种先进先出的行为模式
let color = [];
color.push("red", "green", "blue");
console.log(color[0], color[1], color[2]) // "red", "green", "blue"
console.log(color.length); // 3
color.shift();
console.log(color[0], color[1], color[2]); // "green", "blue", undefined
console.log(color.length); // 2
我们使用push()
方法将三个字符串推入color数组的末尾,此时color包含了三项值,其长度变成了3,然后再次使用shift()
方法移除掉第一项,再次打印发现第一项"red"已经被移除了,剩余每一项的值前移,第三项变成了undefined
,查看color数组的长度,长度变成了2
我们也可以组合使用unshift()
和pop()
方法,可以从相反的方向模拟队列,即在数组前端添加项,从数组末端移除项
let color = [];
color.unshift("red", "green", "blue");
console.log(color[0], color[1], color[2]) // "red", "green", "blue"
console.log(color.length); // 3
color.pop();
console.log(color[0], color[1], color[2]); // "red", "green", undefined
console.log(color.length); // 2
重排序方法
数组中存在两个可以直接用来重排序的方法:reverse()
和sort()
方法
reverse()
:该方法会翻转数组项的顺序
let nums = [5, 4, 3, 2, 1];
nums.reverse();
console.log(nums); [1, 2, 3, 4, 5];
sort()
:该方法会排序数组,在默认情况下,sort()
方法会升序的排列数组项(最小的项数排在前面),sort()
方法调用每个数组项的toString()
方法,获得用来比较的数值项的字符串形式,然后确定排序顺序,即使数组中每一项都是数值,sort()
方法比较的也是字符串
let nums = [5, 3, 4, 2, 1, 11];
nums.sort();
console.log(nums); // 1, 11, 2, 3, 4, 5
我们对nums数组调用sort()
,但结果显示的并不是我们预期的那样,11排在了2的前面。因为sort()
在比较时,比较的是它们的字符串形式,字符串"11"排在"2"前面
想要正确的排序数组项,可以在sort()
中可以传递进一个比较函数作为参数
function compara(value1, value2) {
if(value1 > value2) {
return 1;
} else if (value1 < value2) {
return -1;
} else {
return 0
}
}
let nums = [5, 3, 4, 2, 1, 11];
nums.sort(compara);
console.log(nums); // 1, 2, 3, 4, 5, 11
操作方法
ECMAScript
为操作已经包含在数组中的项提供了很多方法
concat()
concat()
方法可以基于当前数组中的所有项创建一个新的数组。它会创建出该数组的一个副本,然后将接收到的参数逐个的添加至副本数组的末尾组成一个新的数组,并将这个新的数组返回
如果给concat()
传递一个或多个数组,它会依次将数组中的每一项添加至结果数组中,如果只是传递一个普通的值,这些值就会简单的添加到结果数组
let arr = [1, 2, 3, 4, 5];
let newArr = arr.concat([6, 7, 8]);
console.log(newArr); // 1, 2, 3, 4, 5, 6, 7, 8
slice()
slice()
方法能够基于当前数组中的一项或者多项创建一个新数组,slice()
不会影响原数组
可以给slice()
方法传递两个参数,即要返回项的开始位置和结束位置。在只有一个参数的情况下,slice()
方法返回从指定起始位置到数组末尾的所有项;如果传入两个参数,则返回起始项和结束项之间的每一项,但不会包括结束项
let color = ["red", "green", "blue", "purple", "pink"];
let result1 = color.slice(1);
let result2 = color.slice(1, 3);
console.log(result1); // "green", "blue", "purple", "pink"
console.log(result2); // "green", "blue", "purple"
如果slice()
方法的参数中有一个负数,则用数组长度加上该数来确定相应的位置,如果结束位置小于起始位置,则返回空数组
let arr = [1, 2, 3, 4, 5];
let result1 = arr.slice(-2, -1);
let result2 = arr.slice(3, 4);
let result3 = arr.slice(-1, -2);
console.log(result1); // 2, 3, 4
console.log(result2); // 2, 3, 4
console.log(result3); // []
splice()
splice()
方法可能是最强大的数组方法之一了,它有很多作用,其主要用途是向数组中插入项,使用这种方法的方式有三种
删除
:可以删除任意数量的项,只需要指定2个参数,一个是要删除的第一项的位置和要删除的项数。例如,splice(0, 2)
会删除数组中的前两项插入
:可以向指定位置插入任意数量的项,需要传递三个参数,一个是起始位置,一个是0(表示删除0项),第三个是要插入的项,如果要插入多个项,可以传递第四、第五,以至多个参数替换
:可以将指定位置项替换成我们想替换的项,指定三个参数,起始位置,删除项数,要替换进去的项,替换的项不一定与删除的项数相等
splice()
方法始终会返回一个数组,包含从原始数组中被删除的项,如果没有删除项,则返回空数组
let color = ["red", "green", "blue"];
let removed = color.splice(0, 1); // 删除第一项
console.log(color); // "green", "blue"
console.log(removed); // "red"
removed = color.splice(1, 0, "yellow", "orange"); // 从位置1开始插入两项
console.log(color); // "green", "yellow", "orange", "blue"
console.log(removed); // []
removed = color.splice(1, 1, "red", "purple"); // 插入两项,删除一项
console.log(color); // "green", "red", "purple", "orange", "blue"
console.log(removed); // yellow
join()
join()
方法将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串。如果数组只有一个项目,那么将返回该项目而不使用分隔符。接受一个字符串作为参数来分隔数组的每个元素,如果不传递参数,则默认是用逗号分割,如果传递一个空字符串,则返回结果都是连在一起的字符串
const elements = ['Fire', 'Air', 'Water'];
console.log(elements.join()); // "Fire,Air,Water"
console.log(elements.join('')); // "FireAirWater"
console.log(elements.join('-'));// "Fire-Air-Water"
位置方法
ECMAScript5
为数组实例添加了两个位置方法:indexOf()
和lastIndexOf()
方法。这两个方法都接受两个参数,一个是要查找的项,一个是查找起点位置的索引(可选),其中indexOf()
从数组的开头开始向后查找,lastIndexOf()
从数组的末尾向前查找
这两个方法都返回要查找的项在数组中的位置,或者在没有找到的情况返回-1。在比较第一个参数与数组中的每一项时,会使用全等操作符,即要求查找的项必须严格相等(就像使用===判断一样)
let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
console.log(numbers.indexOf(4)); // 3
console.log(numbers.lastIndexOf(4)); // 5
console.log(numbers.indexOf(4, 4)); // 5
console.log(numbers.lastIndexOf(4, 4)); // 3
迭代方法
ECMAScript5
为数组实例添加了5个迭代方法,每个方法接受两个参数,要在每一项上运行的函数,和运行该函数的作用域对象(可选)
传入的函数接受3个参数,数组项的值、该项在数组中的位置、数组对象本身。根据使用方法不同,函数执行后返回的结果也不同
every()
:对数组中每一项运行给定函数,如果该函数对每一项都返回true
,则返回true
let numbers = [1, 2, 3, 4, 5, 4 , 3, 2, 1];
let everyResult = numbers.every((item, index, array) => {
return item > 2;
});
console.log(everyResult); // false
filter()
:对数组中每一项运行给定函数,返回该函数会返回true
项组成的数组
let numbers = [1, 2, 3, 4, 5, 4 , 3, 2, 1];
let filterResult = numbers.filter((item, index, array) => {
return item > 2;
});
console.log(filterResult); // [3, 4, 5, 4, 3]
forEach()
:对数组中每一项都运行给定函数,该方法没有返回值
let numbers = [1, 2, 3, 4, 5, 4 , 3, 2, 1];
numbers.forEach((item, index, array) => {
console.log("hello world!");
});
map()
:对数组中的每一项运行给定函数,返回每次函数调用结果组成的数组
let numbers = [1, 2, 3, 4, 5, 4 , 3, 2, 1];
let mapResult = numbers.map((item, index, array) => {
return item * 2;
});
console.log(mapResult); // [2, 4, 6, 8, 10, 8, 6, 4, 2]
some()
:对数组中每一项运行给定函数,如果该函数任意有一项返回true
,则返回true
let numbers = [1, 2, 3, 4, 5, 4 , 3, 2, 1];
let someResult = numbers.some((item, index, array) => {
return item > 2;
});
console.log(someResult); // true
以上方法都不会对原数组中的值进行更改
归并方法
ECMAScript5
还增加了两个归并方法,这两个方法都会迭代数组中的所有项,然后构建一个最终返回的值
reduce()
方法对数组中的每个元素执行一个传递进去的函数(升序执行),将其结果汇总为单个返回值
传递进去的函数接受4个参数,前一个值、当前值、项的索引、数组对象。这个函数返回的任何值都会作为第一个参数自动传递给下一项第一次迭代发生在数组的第二项上,因此第一个参数是数组的第一项,第二个参数是数组的第二项
let arr = [1, 2, 3, 4, 5];
let result = arr.reduce((prev, cur, index, array) => {
return prev + cur;
});
console.log(result); // 15
reduceRight()
的作用类似,只不过方向相反
ES6新增
数组解构
ES6中允许从数组中提取值,按照对应位置,对变量赋值
解构赋值就是把数据结构分解,然后给变量进行赋值,如果结构不成功,变量跟数值个数不匹配的时候,变量的值为undefined
let [a, b, c] = [1, 2, 3];
console.log(a)//1
console.log(b)//2
console.log(c)//3
扩展运算符
扩展运算符可以将数组转为用逗号分隔的参数序列
let arr = [1, 2, 3];
...arr // 1, 2, 3
console.log(...arr); // 1 2 3,相当于下面的代码
console.log(1,2,3);
扩展运算符可以应用于合并数组
// 方法一
let arr1 = [1, 2, 3];
let arr2 = [3, 4, 5];
let arr3 = [...arr1, ...arr2];
// 方法二
arr1.push(...arr2);
将伪数组或可遍历对象转换为真正的数组,伪数组没有办法使用数组中常用的这些方法,我们需要将伪数组转换为真正的数组,以此来使用数组中这些便捷的方法
let oDivs = document.getElementsByTagName('div');
oDivs = [...oDivs];
form
将伪数组或可遍历对象转换为真正的数组
//定义一个集合
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};
//转成数组
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
方法还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组
let arrayLike = {
"0": 1,
"1": 2,
"length": 2
}
let newAry = Array.from(arrayLike, item => item *2) // [2,4]
注意:如果是对象,那么属性需要写对应的索引
实例方法
find()
用于找出第一个符合条件的数组成员,如果没有找到返回undefined
let ary = [{
id: 1,
name: '张三'
}, {
id: 2,
name: '李四'
}];
let target = ary.find((item, index) => item.id == 2); // 找数组里面符合条件的值,当数组中元素id等于2的查找出来,注意,只会匹配第一个
findIndex()
用于找出第一个符合条件的数组成员的位置,如果没有找到返回-1
let ary = [1, 5, 10, 15];
let index = ary.findIndex((value, index) => value > 9);
console.log(index); // 2
includes
判断某个数组是否包含给定的值,返回布尔值
[1, 2, 3].includes(2) // true
[1, 2, 3].includes(4) // false