数组操作

206 阅读6分钟

总览

分组 名称 示例
创建数组 方法1 var arr=[]
方法2 var arr=new Array()
方法3 var arr=Array.of(1,2,3)
方法4 var arr = Array.from('hello');
改变原数组 操作-最后一个元素 删除:pop()
添加:push()
操作-第一个元素 删除:shift()
添加:unshift()
颠倒顺序 reverse()
指定位置,删除/添加/替换数组元素 splice()
排序 sort()
复制替换 copyWithin()
批量替换/填充 fill()
不改变原数组 拼接成字符串 join()
(不推荐)toLocaleString()
toString()
浅拷贝 slice()
合并数组 cancat()
查询元素下标 indexOf()
lastIndexOf()
查检测是否包含某元素 includes()
遍历 遍历 forEach()
检测是否-都-符合 every()
检测是否-有-符合的 some()
过滤出符合条件的元素,返回其组成的新数组 filter()
遍历操作每个元素返回新数组 map()
累加 reduce()
reduceRight()
查找元素 find()
查找元素下标 findIndex()
遍历键名、遍历键值、遍历键名+键值(不建议) keys()&values()&entries()

创建数组

便捷创建

var arr = [];
var arr = [1,2,3];

new Array()

var arr = new Array();
var arr = Array();
var arr = Array(3);//[empty × 3];仅写一个数字num,相当于创建length===num的空数组
var arr = Array(1,2,3);//等同于var arr = [1,2,3]

Array.of()

var arr = Array.of(1,2,3);//[1,2,3]
var arr = Array.of(3);//[3]
//等同于arr=[]这种方式

Array.from

var arr = Array.from('hello');//['h','e','l','l','o'];
var arr = Array.from( [1,2,3] , (x) = > x * x );//[1,4,9]
//定义:用于将伪数组转换为真正的数组(不改变原对象,返回新的数组)
//Array.from(input,map,context);    input伪数组,map类似map()方法,对每个元素进行处理后放入生成的新数组,context: 绑定map中用到的this

改变原数组的九个方法

arr.pop()删除并返回数组的最后一个元素

arr.push()向数组末尾添加元素,并返回数组的长度

arr.shift()删除并返回数组的第一个元素

arr.unshift()向数组头部添加元素,并返回数组的长度

arr.reverse()颠倒数组元素顺序

arr.splice()添加、删除/替换数组元素

语法 arr.splice(index,length,item);

参数描述详解
index开始操作的下标(位置),操作时这个位置是在arr[index]前,arr[index-1]后的负数从数组结尾处往前数,'-1'和'arr.length-1'的指向位置是一样的
length操作的长度,用于删除或者替换如果是0,则不会删除或替换,只会在index位置添加item
item用于替换或添加的元素(可以是多个)length===0时是添加,!==0时是替换

添加

var arr = [1,2,3];//[1,2,3]
var ArrRemove = arr.splice(1,0,'a');//向数组arr的下标1前(arr[1]===2),往后数0个元素,替换成'a'
console.log(ArrRemove);//[],因为没有元素被替换,也就是没有元素没删除,所以返回[]
console.log(arr);//[1,'a',2,3];原数组被改变

//上述操作为什么在1和2之间添加了'a'解释
//此时index===1,length===0,item==='a'
//开始操作的位置,在arr[index]前,arr[index-1]后,也就是1和2之间
//在这个位置往后数0个元素,替换成item(也就是'a')
//就做到了再数组元素1和2之间添加了元素'a'

//添加多个元素
var arr=[1,2,3];
arr.splice(2,0,'a','b','c');
console.log(arr);//[1, 2, "a", "b", "c", 3]

删除

var arr = [1,2,3,4,5,6];
var ArrRemove = arr.splice(2,2);//向数组arr的下标2前(arr[2]===3),往后数2个元素,替换成空(因为item不存在),此处视为删除
console.log(ArrRemove);//[3, 4]
console.log(arr);//[1, 2, 5, 6]

替换

var arr = [1,2,3,4,5,6];
var ArrRemove = arr.splice(2,2,'a')//向数组arr的下标2前,往后数两个元素,替换成'a'
console.log(ArrRemove);//[3, 4]
console.log(arr);//[1, 2, "a", 5, 6];此处3,4被替换成了'a'

总结

  1. arr[index]前的位置,往后数length个元素,替换成item
  2. 往后数0个元素,替换成item视为添加
  3. 往后数length个元素,替换成空视为删除
  4. 往后数length个元素,替换成item视为替换

arr.sort()排序

没有比较函数时,默认按字母升序,不是字符串则将元素转为字符串的万国码Unicode进行比较排序
比较函数的两个参数:

  1. sort的比较函数有两个默认参数,要在函数中接收这两个参数,这两个参数是数组中两个要比较的元素,通常我们用 a 和 b 接收两个将要比较的元素;
  2. 若比较函数返回值<0,那么a将排到b的前面;
  3. 若比较函数返回值=0,那么a 和 b 相对位置不变;
  4. 若比较函数返回值>0,那么b 排在a 将的前面;

升序降序

//升序
var arr = [1,3,2];
arr.sort(function (a,b) {
    return a-b
})
console.log(arr);//[1, 2, 3]

//降序
var arr = [1,3,2];
arr.sort(function (a,b) {
    return b-a
})
console.log(arr);//[3, 2, 1]

//注解,参数a,b理解成相邻的前后两个元素,如果返回值小于0则将a放在b前,大于0则将b放在a前
//默认返回值小于0,a在前的情况下
//升序时,为使返回值a-b<0,需要a<b,达到小的在前面的目的
//降序时,为使返回值b-a<0,需要a>b,达到大的在前面的目的

//默认返回值大于0,b在前的情况下
//升序时,为使返回值a-b>0,需要b<a,达到小的在前面的目的
//降序时,为使返回值b-a>0,需要b>a,达到大的在前面的目的

多条件排序

//假使有这么一组数据,需要安装id的数值升序,id数值相等时,需age的数值降序
var arr = [ {id:10,age:2} , {id:5,age:4} , {id:6,age:10} , {id:9,age:6} , {id:2,age:8} , {id:10,age:9} ];
arr.sort(function(a,b){
    if(a.id === b.id){// 如果id的值相等,按照age的值降序
        return b.age - a.age
    }else{ // 如果id的值不相等,按照id的值升序
        return a.id - b.id
    }
})
console.log(arr);
//0: {id: 2, age: 8}
//1: {id: 5, age: 4}
//2: {id: 6, age: 10}
//3: {id: 9, age: 6}
//4: {id: 10, age: 9}
//5: {id: 10, age: 2}

自定排序规则

//假使有这么一组数据,需要name是'Koro1'的排在前面
var arr = [{name:'Koro1'},{name:'Koro1'},{name:'OB'},{name:'Koro1'},{name:'OB'},{name:'OB'}];
arr.sort(function(a,b){
    if(a.name === 'Koro1'){// 如果name是'Koro1' 返回-1 ,-1<0 a排在b的前面
        return -1
    }else{ // 如果不是的话,a排在b的后面
      return 1
    }
})
console.log(arr);
// [{"name":"Koro1"},{"name":"Koro1"},{"name":"Koro1"},{"name":"OB"},{"name":"OB"},{"name":"OB"}] 

arr.copyWithin() 复制数组本身元素替换数组本身元素

语法 copyWithin( index , CopyStart , CopyEnd );

参数描述详解
index开始操作的位置(类同splice的index)
CopyStart-CopyEnd从arr[CopyStart]到arr[CopyEnd]复制替换内容(复制得到内容类同于spliece用于替换的item)注意两个都是下标,没有长度
  1. 复制本身的一些元素作为item,然后替换数组指定位置后的一些元素
  2. 替换的长度视拷贝的长度而定
  3. 均可负值
  4. 操作后数组长度是不变的
var arr = [1,2,3,'a','b','c','刘','关','张'];
arr.copyWithin(0,3,6);
console.log(arr);//["a", "b", "c", "a", "b", "c", "刘", "关", "张"]
//从arr[3]前复制到arr[6]前,复制了这个三个元素'a','b','c'
//在arr[0]前往后数进行替换,复制了三个,就替换三个,123被替换成了abc

arr.fill()替换数组的元素

语法 fill(item,StartIndex,EndIndex);
理解成和上面splice和copyWithin一样的替换行为就行了

参数描述详解
item填充元素
StartIndex-EndIndex填充位置此处是下标
//案例1
var arr = [1,2,3,4,5,6]
arr.fill('a');
console.log(arr);//["a", "a", "a", "a", "a", "a"]

//案例2
var arr = [1,2,3,4,5,6]
arr.fill('a',2,4);
console.log(arr);//[1, 2, "a", "a", 5, 6]

//案例3
var arr = new Array(4);
arr.fill('yes')
console.log(arr);//["yes", "yes", "yes", "yes"]


//案例4
var arr = new Array(4);
arr.fill(null)
console.log(arr);//[null, null, null, null]

不改变原数组的8个方法

join() 按分割符将数组元素拼接成一个字符串

let a= ['hello','world'];
let str=a.join(); // 'hello,world'
let str2=a.join('+'); // 'hello+world'
// 默认','逗号
// 元素是数组时,元素数组也按此处理
// 元素数组是对象时,按[object Object]字符串处理

toLocaleString() 数组转字符串

// 等同join(),只不过在join前先将每个元素都toLocaleString()再拼接,而且不能填写参数,默认逗号分割拼接
// toLocaleString的详解:
// https://blog.csdn.net/weixin_39749820/article/details/82869537

toString() 数组转字符串 不推荐

//相当于不能自定义分隔符的join
//当数组和字符串操作的时候,js 会调用这个方法将数组自动转换成字符串
let a= ['调用toString','连接在我后面']+'啦啦啦'; // 调用toString,连接在我后面啦啦啦

slice() 浅拷贝数组的元素

slice(start,end)//从start,可负值,默认0;到end截止,不可负值,默认length-1
//是浅拷贝
//简单数据类型时可不互相影响
//该方法同样适用于字符串string,或者说字符串也有slice()方法。string是伪数组因而一法两用吧

cancat()合并两个或多个数组,返回一个新数组

var newArr=arr1.cancat(arr2,arr3)//参数数组可以多个,但至少一个,参数也可是具体的值
ES6扩展运算符...合并数组:{
    var newArr=[...arr1,...arr2,1,2,3]
    //扩展运算符(spread)是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。
    //类同于把参数数组[1,2]变成了1,2把数组的每一个元素都单拎出来作为一个参数
}

indexOf()查找数组是否包含某个元素,并返回下标

array.indexOf(string,startIndex)
//string被查找的元素,startIndex开始查找的位置,默认0,可负,不能大于数组长度
//不存在,返回-1。存在返回index
//不能识别NAN
//查找匹配时严格全等===

lastIndexOf() 查找指定元素在数组中的最后一个位置

array.lastIndexOf(string,startIndex)//string被查找的元素,startIndex开始查找的位置,默认-1
//因为是查找最后出现的下标,所以是从startIndex往前(index=0)方向查的,包括下标指向元素自身
//类同indexOf,查找到返回下标,查找不到返回-1

ES7 includes() 查找数组是否包含某个元素 返回布尔

includes(string,statrIndex)//string被查找的元素,startIndex开始朝招的位置,可负,默认0
//不再返回下标,按照查询结果返回true或者false
//可以查询NAN

遍历的12个方法

ES5:{forEach、every 、some、 fliter、map、reduce、reduceRight}
ES6:{find、findIndex、keys、values、entries}
关于遍历:{
   关于遍历的效率,可以看一下这篇详解JS遍历
    尽量不要在遍历的时候,修改后面要遍历的值
    尽量不要在遍历的时候修改数组的长度(删除/添加)
}

forEach()遍历数组进行操作

array.forEach(function(item, index, arr), thisValue)
// item数组的每一项元素,index是item的下标,arr数组对象本身
// 定义: 按升序为数组中含有效值的每一项执行一次回调函数。
// 无法中途退出循环,return只能退出当前回调
// 不能return值出来,总是返回undefined
// 遍历次数再第一次循环前就会确定,遍历过程中数组添加的元素不会被循环执行回调

every()检测数组所有元素是否都符合判断条件

array.every(function(item, index, arr), thisValue)
// 检测所有元素,有一个不满足就返回false终止循环,都满足返回true

some()数组中的是否有满足判断条件的元素

array.some(function(item, index, arr), thisValue)
// 检测所有元素,有一个满足就返回true终止循环,如果都不满足则返回false

filter()过滤返回满足条件的元素组成的新数组

arr.filter(function(item, index, arr), thisArg)

map()对数组中的每个元素进行处理,返回新的数组

new_array = arr.map(function(item, index, arr), thisArg)
//和上面的不同是,上面的fn都是return的布尔值,这个是return当前item处理过的新元素

reduce()为数组提供累加器,合并为一个值

// 累计计算数组的每一个元素
array.reduce(function(total, item, index, arr), firstTotal)
// firstTotal初始值,total累加结果

// 数组求和 
let sum = [0, 1, 2, 3].reduce(function (a, b) {
     return a + b;
}, 0);
// 6

// 将二维数组转化为一维 将数组元素展开
let flattened = [[0, 1], [2, 3], [4, 5]].reduce(
     (a, b) => a.concat(b),
     []
);
// [0, 1, 2, 3, 4, 5]

reduceRight()从右至左累加

// 类同reduce()

find()& findIndex() 根据条件找到数组成员

arr.find(function(item, index, arr), thisArg)
// 找到并返回第一个满足条件的元素,没有则返回undefined

arr.findIndex(function(item, index, arr), thisArg)
// 找到并返回第一个满足条件的元素的下标,没有则返回-1

ES6 keys()&values()&entries() 遍历键名、遍历键值、遍历键名+键值

//个人感觉不常用,兼容也不好
定义:{三个方法都返回一个新的 Array Iterator 对象,对象根据方法不同包含不同的值。}
语法:{
    array.keys()
    array.values()
    array.entries()
}
参数:无。
遍历栗子(摘自ECMAScript 6 入门):{
    for (let index of ['a', 'b'].keys()) {
     console.log(index);
    }
    // 0
    // 1

    for (let elem of ['a', 'b'].values()) {
     console.log(elem);
    }
    // 'a'
    // 'b'

    for (let [index, elem] of ['a', 'b'].entries()) {
     console.log(index, elem);
    }
    // 0 "a"
    // 1 "b"
}
在for..of中如果遍历中途要退出,可以使用break退出循环。
如果不使用for...of循环,可以手动调用遍历器对象的next方法,进行遍历:{
    let letter = ['a', 'b', 'c'];
    let entries = letter.entries();
    console.log(entries.next().value); // [0, 'a']
    console.log(entries.next().value); // [1, 'b']
    console.log(entries.next().value); // [2, 'c']
}
entries()浏览器兼容性(MDN):Chrome 38, Firefox 28,Opera 25,Safari 7.1
keys()浏览器兼容性(MDN):Chrome 38, Firefox 28,Opera 25,Safari 8,
注意:目前只有Safari 9支持,,其他浏览器未实现,babel转码器也还未实现