# Javascript 数组的操作总结
# 数组的创建
数组的创建分为以下几种
# 字面量创建
const arry = []
这是我们平时使用最多,最简单的数组创建方式。
# 构造函数创建
const arr1 = Array(3) // [empty × 3]
const arr2 = Array('3') // ["3"]
arr1.length // 3
arr2.length // 1
这种方式创建的数组属于稀疏数组,每一项都是空位,下边会具体介绍稀疏数组。 请避免使用这样的方式创建数组。
# of() 方法
const arr1 = Array.of(3) // [3]
const arr2 = Array.of('3') // ['3']
这是 ES6 中新增的方法,用来弥补构造函数的的缺陷。 不会根据参数的类型不同导致创建行为的不同。
# from() 方法
const arr1 = Array.from({length: 3}) // [undefined, undefined, undefined]
ES6 新增的方法,这个方法的主要用途就是将 类数组对象转为数组对象。 创建给定长度的数组这个方法会很好用。
TIP
ES5 类数组对象转为数组对象
Array.prototype.slice.call(elems)
# 数组遍历
# 一些常用方法
- for
- forEatch
这两个方法遍历的效率最高
需要注意的是:
return false 不能打断 forEatch 可以通过抛出异常(throw)的形式打断forEatch循环
虽然forEach不能直接遍历对象,但它可以通过call方式遍历类数组对象。如下
const o = {0:1, 1:3, 2:5, length:3};
Array.prototype.forEach.call(o,function(value, index, obj){
console.log(value,index);
},o);
# map
map() 方法遍历数组,使用传入函数处理每个元素,并返回函数的返回值组成的新数组。且不改变原数组
const arry = [1,2,3,4]
const arry2 = arry.map((item)=>{
return item +1
})
console.log(arry,arry2) // [1,2,3,4] [2,3,4,5]
# every
every() 方法使用传入的函数测试所有元素,只要其中有一个函数返回值为 false,那么该方法的结果为 false;如果全部返回 true,那么该方法的结果才为 true
const arry = [1,2,3,4]
const arry2 = arry.every((item)=>{
return item>3
})
console.log(arry2) //false
# some
some() 方法刚好同 every() 方法相反,传入测试数组元素时,只要有一个函数返回值为 true,则该方法返回 true,若全部返回 false,则该方法返回 false
const arry = [1,2,3,4]
const arry2 = arry.some((item)=>{
return item>3
})
console.log(arry2) //true
# filter
filter() 方法使用传入的函数测试所有元素,并返回所有通过测试的元素组成的新数组。它就好比一个过滤器,筛掉不符合条件的元素
const array = [18, 9, 10, 35, 80];
const array2 = array.filter((value, index, array)=>{
return value > 20;
});
console.log(array2); // [35, 80]
# reduce
reduce() 方法接收一个方法作为累加器,数组中的每个值(从左至右) 开始合并,最终为一个值。
const array = [1,2,3,4]
array.reduce((p, v) => p * v); // 24
# find&findIndex(ES6)
find() 方法基于ECMAScript 2015(ES6)规范,返回数组中第一个满足条件的元素(如果有的话), 如果没有,则返回undefined。
findIndex() 方法也基于ECMAScript 2015(ES6)规范,它返回数组中第一个满足条件的元素的索引(如果有的话)否则返回-1。
const arry = [1,2,3,4]
const arry2 = arry.find((item)=>{
return item>3
})
console.log(arry2) // 4
--------------------------------------------------------------------
const arry = [1,2,3,4]
const arry2 = arry.findIndex((item)=>{
return item>3
})
console.log(arry2) // 3
# 改变自身值的方法
# pop()
pop() 方法删除一个数组中的最后的一个元素,并且返回这个元素。如果是栈的话,这个过程就是栈顶弹出。
const array = ["cat", "dog", "cow", "chicken", "mouse"];
const item = array.pop();
console.log(array); // ["cat", "dog", "cow", "chicken"]
console.log(item); // mouse
pop方法可以应用在类数组对象上
const o = {0:"cat", 1:"dog", 2:"cow", 3:"chicken", 4:"mouse", length:5}
const item = Array.prototype.pop.call(o);
console.log(o); // Object {0: "cat", 1: "dog", 2: "cow", 3: "chicken", length: 4}
console.log(item); // mouse
但如果类数组对象不具有length属性,那么该对象将被创建length属性,length值为0。如下
const o = {0:"cat", 1:"dog", 2:"cow", 3:"chicken", 4:"mouse"}
const item = Array.prototype.pop.call(o);
console.log(array); // Object {0: "cat", 1: "dog", 2: "cow", 3: "chicken", 4: "mouse", length: 0}
console.log(item); // undefined
# push unshift
push()方法添加一个或者多个元素到数组末尾,并且返回数组新的长度。如果是栈的话,这个过程就是栈顶压入
unshift() 方法用于在数组开始处插入一些元素(就像是栈底插入),并返回数组新的长度
const arry = [1,2,3]
arry.push(4)
console.log(arry) // [1,2,3,4]
同pop方法一样,push方法也可以应用到类数组对象上,如果length不能被转成一个数值或者不存在length属性时,则插入的元素索引为0,且length属性不存在时,将会创建它
# reverse
reverse() 方法颠倒数组中元素的位置,第一个会成为最后一个,最后一个会成为第一个,该方法返回对数组的引用
const array = [1,2,3,4,5];
const array2 = array.reverse();
console.log(array); // [5,4,3,2,1]
# shift
shift()方法删除数组的第一个元素,并返回这个元素。如果是栈的话,这个过程就是栈底弹出
const array = [1,2,3,4,5];
const item = array.shift();
console.log(array); // [2,3,4,5]
console.log(item); // 1
# sort
sort()方法对数组元素进行排序,并返回这个数组
const arry = [1,2,6,8,3,4]
const arry2 = arry.sort((a,b)=>{
return a>b
})
console.log(arry2) // [1,2,3,4,6,8]
--------------------------------------------
const arry3 = arry.sort((a,b)=>{
return a<b
})
console.log(arry3) // [8,6,4,3,2,1]
# splice
splice()方法用新元素替换旧元素的方式来修改数组。它是一个常用的方法,复杂的数组操作场景通常都会有它的身影,特别是需要维持原数组引用时,就地删除或者新增元素,splice是最适合的。
语法:arr.splice(start,deleteCount[, item1[, item2[, …]]])
start 指定从哪一位开始修改内容。如果超过了数组长度,则从数组末尾开始添加内容;如果是负值,则其指定的索引位置等同于 length+start (length为数组的长度),表示从数组末尾开始的第 -start 位。
deleteCount 指定要删除的元素个数,若等于0,则不删除。这种情况下,至少应该添加一位新元素,若大于start之后的元素总和,则start及之后的元素都将被删除。
itemN 指定新增的元素,如果缺省,则该方法只删除数组元素。
返回值 由原数组中被删除元素组成的数组,如果没有删除,则返回一个空数组。
const array = ["apple","boy"];
const splices = array.splice(1,1);
console.log(array); // ["apple"]
console.log(splices); // ["boy"] ,可见是从数组下标为1的元素开始删除,并且删除一个元素,由于itemN缺省,故此时该方法只删除元素
array = ["apple","boy"];
splices = array.splice(2,1,"cat");
console.log(array); // ["apple", "boy", "cat"]
console.log(splices); // [], 可见由于start超过数组长度,此时从数组末尾开始添加元素,并且原数组不会发生删除行为
array = ["apple","boy"];
splices = array.splice(-2,1,"cat");
console.log(array); // ["cat", "boy"]
console.log(splices); // ["apple"], 可见当start为负值时,是从数组末尾开始的第-start位开始删除,删除一个元素,并且从此处插入了一个元素
array = ["apple","boy"];
splices = array.splice(-3,1,"cat");
console.log(array); // ["cat", "boy"]
console.log(splices); // ["apple"], 可见即使-start超出数组长度,数组默认从首位开始删除
array = ["apple","boy"];
splices = array.splice(0,3,"cat");
console.log(array); // ["cat"]
console.log(splices); // ["apple", "boy"], 可见当deleteCount大于数组start之后的元素总和时,start及之后的元素都将被删除
# fill(ES6)
fill() 方法基于ECMAScript 2015(ES6)规范,它同样用于数组元素替换,但与copyWithin略有不同,它主要用于将数组指定区间内的元素替换为某个值。
语法:arr.fill(value, start[, end = this.length])
value 指定被替换的值,start 指定替换元素起始的索引,end 可选,指的是替换元素结束位置的索引。
如果start为负,则其指定的索引位置等同于length+start,length为数组的长度。end也是如此。
const array = [1,2,3,4,5];
const array2 = array.fill(10,0,3);
console.log(array===array2,array2); // true [10, 10, 10, 4, 5], 可见数组区间[0,3]的元素全部替换为10
# 不改变自身值的方法
# concat
concat() 方法将传入的数组或者元素与原数组合并,组成一个新的数组并返回。
const a = [1,2,3]
const b = a.concat([4,5,6])
console.log(b) // [1,2,3,4,5,6]
TIP
若concat方法中不传入参数,那么将基于原数组浅复制生成一个一模一样的新数组(指向新的地址空间
# join
join() 方法将数组中的所有元素连接成一个字符串。
const a = ['码不','停息'];
console.log(a.join()) // 码不,停息
console.log(a.join('+')) // 码不+停息
console.log(a.join('')) // 码不停息
# toString
toString()方法返回数组的字符串形式,该字符串由数组中的每个元素的 toString() 返回值经调用 join() 方法连接(由逗号隔开)组成
const a = ['码不','停息'];
console.log(a.toString()) //码不,停息
TIP
和toString类似的还有toLocaleString
# indexOf lastIndexOf includes
indexOf() 方法用于查找元素在数组中第一次出现时的索引,如果没有,则返回-1。
lastIndexOf() 方法用于查找元素在数组中最后一次出现时的索引,如果没有,则返回-1。并且它是indexOf的逆向查找,即从数组最后一个往前查找
includes() 方法基于ECMAScript 2016(ES7)规范,它用来判断当前数组是否包含某个指定的值,如果是,则返回 true,否则返回 false。
TIP
indexOf 和includes 唯一的区别就是includes能够发现NaN,而indexOf不能
const a = [1,2,3,NaN,2];
console.log(a.indexOf(2)) //1
console.log(a.lastIndexOf(2)) // 4
console.log(a.indexOf(NaN)) // -1
console.log(a.includes(NaN)) // true
# 数组扁平化
# 调用ES6中的flat方法 flat
const list = [[1,2],[3],4]
const ls = list.flat(Infinity)
# replace + split
const list = [[1,2],[3],4]
const ls = list.replace(/(\[|\])/g, '').split(',')
# 普通递归
let result = [];
let fn = function(ary) {
for(let i = 0; i < ary.length; i++) {
let item = ary[i];
if (Array.isArray(ary[i])){
fn(item);
} else {
result.push(item);
}
}
}
# 扩展运算符
const ary = [[1,2],[3],4];
while (ary.some(Array.isArray)) {
ary = [].concat(...ary);
}
# 总结
关于数组的API实在是太多,我们可以总结下,方便记忆
# 数组遍历
for循环遍历每一个元素forEatch循环遍历每一个元素 return false 无效map循环遍历每一个元素 返回新数组some只要有一个函数返回值为 true,则该方法返回 trueevery只要其中有一个函数返回值为 false,那么该方法的结果为 falsefilter过滤器,筛掉不符合条件的元素reduce累加器 返回最终结果
# 增
push在数组最后追加unshift在数组最前增加splice当第一个参数超过数组长度,此时从数组末尾开始添加元素 (不常用)
# 删
pop删除数组最后一个元素shift删除数组第一个元素splice删除数组指定下标元素
# 查
indexOf有返回下标 否则返回-1lastIndexOfindexOf的逆向查找 有返回下标 否则返回-1includes能够发现NaN 有返回true 否则返回false
# 组合
concat拼接两个数组jointoString把数组凭借为字符串