JavaScript的数组
JavaScript数组也是对象,它使用单一的变量存储一系列的值。
数组和对象的区别
在JavaScript中,数组必须使用数字索引,对象可以使用命名索引。
数组是特殊类型的对象,具有特有的一些属性和方法。
如何区分数组和对象
方案1
ECMAScript5定义新方法Array.isArray()
1 | var arr = []; |
此方案不支持老的浏览器。
方案2
1 | var arr = []; |
创建
使用字面量创建
1 | var arr = []; |
使用构造函数创建
1 | var arr = new Array(); |
出于简洁、可读性和执行速度的考虑,建议使用第一种方法。
取值
1 | var arr = [1, 2]; |
修改值
1 | var arr = [1, 2]; |
超过数组长度赋值、取值
1 | var arr = [1, 2]; |
删除元素
数组属于对象,所以可以使用delete运算符执行删除操作
1 | var arr = [0]; |
元素长度length
1 | var arr = [1, 2]; |
for循环遍历
1 | var arr = [1, 2]; |
for…in循环遍历
1 | var arr = [1, 2]; |
concat()-合并两个或多个数组
1 | var arr1 = [1]; |
不会改变原数组
join()-将数组元素拼接成一个字符串
1 | var arr = [1, 2]; |
不会改变原数组
sort()-排序
1 | var arr = [1, 2]; |
返回对数组的引用,在原数组上进行排序,不生成副本。
说明
函数中比较如果小于零,则排序结果item1在前,item2在后。即
return item1 - item2
为升序,反之return item2 - item1
为降序。所以return 0.5 - Math.random()
可以实现随机排序。sort也可以对文字排序,和数字排序一样,遵从ASCII编码的排序规则
查找最值
方案一
查找最小值(最大值同理)
1 | var arr = [1, 2]; |
需要对数组进行排序,效率较低
方案二1
2
3
4
5
6
7
8
9
10
11var arr = [1, 2];
function getArrMax(arr) {
return Math.max.apply(null, arr);
}
function getArrMin(arr) {
return Math.min.apply(null, arr);
}
console.log(getArrMax(arr));
// 2
console.log(getArrMin(arr));
// 1
pop()-删除并返回数组的最后一个元素
1 | var arr = [1, 2]; |
会改变原数组
push()-向数组的末尾添加一个或多个元素,并返回新的长度
1 | var arr = [1, 2]; |
会改变原数组
push()方法和pop()方法使用数组提供的先进后出栈的功能。
reverse()-颠倒数组中元素的顺序
1 | var arr = [1, 2]; |
会改变原数组
shift()-删除数组第一个元素,并返回第一个元素的值
1 | var arr = [1, 2]; |
会改变原数组
unshift()-向数组的开头添加一个或更多元素,并返回新的长度
1 | var arr = [1]; |
改变原有的数组
slice()-返回选定的元素
1 | arrayObject.slice(start,end) |
start、end都可以使用负值从数组的尾部选取元素,1
2
3
4
5var arr = [1, 2, 3];
console.log(arr.slice(1, 2));
// [2]
console.log(arr);
// [1, 2, 3]
不会改变原数组,如果需要删除数组中的一段元素,应该使用方法
Array.splice()
splice()-从数组中添加/删除元素,返回被删除元素
1 | arrayObject.splice(index,howmany,item1,.....,itemX) |
howmany如果设置为0,则不会删除项目。1
2
3
4
5var arr = [1, 2, 3, 4, 5];
console.log(arr.splice(2, 1, 6));
// [3]
console.log(arr);
// [1, 2, 6, 4, 5]
改变原始数组。
toString()-将数组转换为字符串
1 | var arr = [1, 2, 3]; |
返回值与没有参数的join()方法返回的字符串相同,元素之间用逗号分隔
toLocaleString()-把数组转换为本地字符串
首先调用每个数组元素的toLocaleString()方法,然后使用地区特定的分隔符把生成的字符串连接起来,形成一个字符串。1
2
3var arr = ['a', 'b', 'c'];
console.log(arr.toLocaleString());
// a,b,c
valueOf()-返回Array对象的原始值
1 | var arr = [1, 2]; |
通常由JavaScript在后台自动调用,并不显式地出现在代码中。
forEach()-为每个元素调用一次函数
1 | var arr = [1, 2]; |
不改变原数组
map()-对每个元素执行函数来创建新数组
1 | var arr = [1, 2]; |
不改变原数组
filter()-通过测试的元素创建新数组
1 | var arr = [1, 2]; |
不改变原数组
reduce()-每个元素运行函数,以生成(减少它)单个值。从左到右工作
1 | var arr = [1, 2, 3]; |
可以接受一个初始值1
2
3
4
5
6
7
8var arr = [1, 2, 3];
var sum = arr.reduce(function (total, value, index, array) {
return total + value;
}, 4);
console.log(sum);
// 10
console.log(arr);
// [1, 2, 3]
reduceRight()-每个元素运行函数,以生成(减少它)单个值。从右到左工作
1 | var arr = [1, 2, 3]; |
every()-检查所有数组值是否通过测试
1 | var arr = [1, 2, 3]; |
some()-检查某些数组值是否通过测试
1 | var arr = [1, 2, 3]; |
indexOf()-搜索元素值并返回其位置
1 | array.indexOf(item, start) |
item 必需。要检索的项目。
start 可选。从哪里开始搜索。负值将从结尾开始的给定位置开始,并搜索到结尾。
未找到项目返回-1。
项目多次出现,返回第一次出现的位置。1
2
3var arr = [1, 2, 3];
console.log(arr.indexOf(2));
// 1
lastIndexOf()-搜索元素值并返回其位置,从结尾开始搜索
1 | array.lastIndexOf(item, start) |
item 必需。要检索的项目。
start 可选。从哪里开始搜索。负值将从结尾开始的给定位置开始,并搜索到开头。1
2
3var arr = [1, 2, 3];
console.log(arr.lastIndexOf(2));
// 1
find()-返回通过测试函数的第一个元素的值
1 | var arr = [1, 2, 3]; |
findIndex()-返回通过测试函数的第一个元素的索引
1 | var arr = [1, 2, 3]; |
es6中的数组操作
Array.from()-将类似数组的对象(array-like object)和可遍历(iterable)的对象(包括ES6新增的数据结构Set和Map)转为真正的数组
所谓类似数组的对象,本质特征只有一点,即必须有length属性。1
2
3
4
5
6
7
8
9
10
11var arrLike = {
"0": 1,
"1": 2,
length: 2,
};
// ES5的写法
console.log([].slice.call(arrLike));
// [1, 2]
// ES6的写法
console.log(Array.from(arrLike));
// [1, 2]
只要部署了Iterator接口的数据结构,Array.from都能将其转为数组,如Set和Map。1
2
3var set = new Set([1, 2])
console.log(Array.from(set));
// [1, 2]
Array.from还可以接受第二个参数,作用类似于数组的map方法。1
2
3
4
5
6
7var arrLike = {
"0": 1,
"1": 2,
length: 2,
};
console.log(Array.from(arrLike, value => value *2));
// [2, 4]
如果map函数里面用到了this关键字,还可以传入Array.from的第三个参数,用来绑定this。1
2
3
4
5
6
7
8
9
10var arrLike = {
"0": 1,
"1": 2,
length: 2,
};
var context = {
key: 1,
}
console.log(Array.from(arrLike, function () { return this.key *2 }, context));
// [2, 2]
Array.of()-将一组值转换为数组
1 | console.log(Array.of(1, 2)); |
参数个数不同,不会有像new Array()一样行为有差异。
Array.of()的模拟实现1
2
3function ArrayOf(){
return [].slice.call(arguments);
}
Array.prototype.copyWithin()-在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。
1 | Array.prototype.copyWithin(target, start = 0, end = this.length) |
- target(必需):从该位置开始替换数据。如果为负值,表示倒数。
- start(可选):从该位置开始读取数据,默认为 0。如果为负值,表示从末尾开始计算。
- end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示从末尾开始计算。
1
2
3
4
5var arr = [1, 2, 3, 4, 5];
console.log(arr.copyWithin(0, 3));
// [4, 5, 3, 4, 5]
console.log(arr);
// [4, 5, 3, 4, 5]
Array.prototype.fill()-使用给定值,填充一个数组
1 | arr.fill(value, start, end); |
1 | console.log([1, 2, 3].fill(4, 1, 2)); |
Array.prototype的entries()、keys()和values()
keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17for (let index of [1, 2].keys()) {
console.log(index);
}
// 0
// 1
for (let value of [1, 2].values()) {
console.log(value);
}
// 1
// 2
for (let [index, value] of [1, 2].entries()) {
console.log(index, value);
}
// 0 1
// 1 2
Array.prototype.includes()-表示数组是否包含给定的值,与字符串的includes方法类似。
1 | Array.prototype.includes(value, start); |
该方法的第二个参数表示搜索的起始位置。1
2
3
4console.log([1, 2, 3].includes(3, 3));
// false
console.log([1, 2, 3].includes(3, -1));
// true
includes不会导致对NaN的误判
Array.prototype.flat()-将嵌套的数组“拉平”
1 | console.log([1, 2, [3, 4]].flat()); |
flat()的参数代表“拉平”几层的嵌套数组,使用Infinity关键字,不管多少层嵌套,都可以转成一维数组。
Array.prototype.flatMap()-对原数组的每个成员执行一个函数,对返回值组成的数组执行flat()方法
1 | arr.flatMap(function callback(currentValue, index, array) { |
1 | console.log([2, 3, 4].flatMap((x) => [x, x * 2])); |
只能展开一层数组。1
2console.log([1, 2, 3, 4].flatMap(x => [[x * 2]]));
// [[2], [4], [6], [8]]