数组在javascript中使用度很是频繁,我总结了一些在数组中很常见的问题。javascript
关于数组中的方法很是多,我总结了一张表来大体了解数组中的方法java
Array中的方法 | 含义 | 改变原数组 | 返回值 | ES6新增 |
---|---|---|---|---|
concat | 合并两个或多个数组 | false | 新数组 | false |
copyWithin | 浅复制数组的一部分到同一数组中的另外一个位置 | true | 改变后的数组 | true |
entries | 返回数组迭代器对象,该对象包含数组中每一个索引的键/值对 | false | 数组迭代器 | true |
every | 测试数组的全部元素是否都经过了指定函数的测试 | false | 布尔值,true/false | false |
fill | 用一个固定值填充一个数组中从起始索引到终止索引内的所有元素 | true | 改变后的数组 | true |
filter | 建立一个新数组, 其包含经过所提供函数实现的测试的全部元素 | false | 新数组 | false |
find | 返回数组中知足提供的测试函数的第一个元素的值。不然返回undefined | false | javascript语言类型 | true |
findIndex | 返回数组中知足提供的测试函数的第一个元素的索引。不然返回-1 | false | 数组索引 | true |
forEach | 遍历数组 | false | undefined | false |
includes | 判断一个数组是否包含一个指定的值 | false | 布尔值,true/false | true |
indexOf | 返回在数组中能够找到一个给定元素的第一个索引,若是不存在,则返回-1 | false | 数组索引 | false |
join | 将数组(或一个类数组对象)的全部元素链接到一个字符串中 | false | 字符串 | false |
keys | Array迭代器,它包含数组中每一个索引的键 | false | 数组迭代器 | true |
lastIndexOf | 返回指定元素在数组中的最后一个的索引,若是不存在则返回 -1 | false | 数组索引 | false |
map | 遍历数组 | false | 新数组 | false |
pop | 从数组中删除最后一个元素,并返回该元素的值 | true | 数组元素 | false |
push | 将一个或多个元素添加到数组的末尾,并返回新数组的长度 | true | 数组长度 | false |
reduce | 对累加器和数组中的每一个元素(从左到右)应用一个函数,将其减小为单个值 | false | 函数返回值 | false |
reduceRight | reduce执行方向相反,从右到左 | false | 函数返回值 | false |
reverse | 将数组中元素的位置颠倒 | true | 改变后的数组 | false |
shift | 从数组中删除第一个元素,并返回该元素的值 | true | 数组元素 | false |
slice | 可从已有的数组中返回选定的元素 | false | 新数组 | false |
some | 测试数组中的某些元素是否经过由提供的函数实现的测试 | false | 布尔值,true/false | false |
sort | 在适当的位置对数组的元素进行排序 | true | 一个新数组 | false |
splice | 删除现有元素和/或添加新元素来更改一个数组的内容 | true | 删除的元素数组 | false |
toLocaleString | 返回一个字符串表示数组中的元素 | false | 字符串 | false |
toString | 返回一个字符串,表示指定的数组及其元素 | false | 字符串 | false |
unshift | 将一个或多个元素添加到数组的开头 | true | 数组长度 | false |
values | 一个数组迭代器对象,该对象包含数组每一个索引的值 | false | 数组迭代器 | true |
从这个表中咱们要当心几个方法,reverse和sort会改变原数组,并返回改变的新数组,push和unshift方法返回的是数组长度而不是数组,forEach方法返回的是undefined不是数组。数组
此外,我还需提一下slice和splice这两个方法,说实话这两个方法看起来很像,容易让人搞混,最关键的是用到的频率还蛮高的,这两个方法就像字符串中substr和substring这两个老兄弟,闲着没事就喜欢去迷惑别人,本人就曾深深的被这两个方法伤害过。app
slice接受两个参数start和end,表明须要截取的数组的开始序号和结束序号。函数
var arr = [4,3,5,8,9,6]; arr.slice(0) // [4,3,5,8,9,6],end能够省略,默认为数组长度 arr.slice(0,4) //[4,3,5,8] arr.slice(-1); //[6], start为负数表明从数组截取的开始序号从尾部算起 arr.slice(0,-1); //[4,3,5,8,9] end为负数表示结束序号从尾部算起 arr.slice(2,0); //[] arr.slice(-1,-1); //[] 若是start和end符号相同,end必定大于start,不然返回的会是[]
splice的参数为index,deleteCount和...items,index表示须要删除或添加原数时的位置,负数表示从尾部算起,deleteCount表示要删除的元素,0表示不删除。其中items表示添加的元素个数。学习
var arr = [4,3,5,8,9,6]; arr.splice(0,0) //返回[], arr=[4,3,5,8,9,6]; arr.splice(0,2) //返回[4,3], arr=[5,8,9,6]; arr.splice(0,2,3,4) //返回[5,8], arr=[3,4,9,6];
splice不论是添加仍是删除元素,返回的都是删除元素的列表,splice是先作删除操做,后添加测试
var arr = [4,3,5]; arr.splice(3,1,8,9); //返回[], arr= [4, 3, 5, 8, 9]; //若是index大于数组长度,那么splice不会删除元素
注意:虽然slice和splice都返回一个新的数组,可是slice不会改变原数组,splice会改变原数组,这个区别很是关键。this
最后在加一些常常会问到的数组问题。code
//数组字面量建立 var arr = [1,2]; //Array构造器建立; var arr = Array(1,2); //[1,2] 能够用new操做符,也能够不用 //Array构造器有个局限性,不能建立只有单个数字的数组 var arr = Array(10) //建立的是一个长度为10的空数组,并非[10] //若是传入的不是Number类型的数字,那么没有任何问题 var arr = Array('10') //['10'] //此时若是要建立只有单个数字的数组,能够用Array.of方法 var arr = Array.of(10) //[10] var arr = Array.of(1,2) //[1,2] //Array.from( items [ , mapfn [ , thisArg ] ] ) //items是个可迭代对象,mapfn是遍历该迭代对象的function,thisArg是mapfn中的this对象 var arr = Array.from([1,2,3]) //[1,2,3]
Array.from是很是有用的建立数组方法,能把字符串转化为数组,Map,Set也能转成数组。对象
Array.from('abc') //['a','b','c']; Array.from(new Set([1,2,3])) //[1,2,3],固然这个例子毫无心义 Array.from(new Map([[1,2],[3,4]])) //[[1,2],[3,4]]
咱们知道用Array构造器建立的数组是个空数组,map,forEach方法并不能遍历这个数组。
var arr = Array(10); arr.forEach((item,index) => console.log(index)) //不会有输出 //map,forEach循环判断的是该对象上有没有对应的属性 arr.hasOwnProperty(0) //false,以hasOwnProperty为判断标准 //Array.from中的mapfn方法是以迭代方式来判断的,所以 Array.from(arr,(item,index)=>console.log(index)) //0,1,2,3,4,5,6,7,8,9
因为这个缘由,咱们能够快速对数组初始化,好比建立一个0到99的数组
Array.from(Array(100),(item,index)=>index); //固然,若是你用到上表中Array的keys方法那更快捷 Array.from(Array(100).keys());
方法一,建立对象的键值惟一性来进行去重:
var arr = [1,2,3,1,3,5,3,2]; var _arr = []; var obj = {}; arr.forEach(item => { if(!obj[item]){ _arr.push(item); obj[item] = true; } }) arr = _arr;
方法二,结合Set的键值惟一性以及Array.from方法能够快速数组去重:
var arr = Array.from(new Set([1,2,3,1,3,5,3,2])) //[1,2,3,5]
var arr = [1,2,3,4]; var arr1 = arr.slice(); var arr2 = arr.concat();
注:这里的复制指的是浅拷贝
这里的数组指的是全是数字的数组
方法一,sort排序后取值
var arr = [1,4,6,2,33,19,6,9]; var maxvalue = arr.sort((a,b) => b>a )[0] var minvalue = arr.sort((a,b) => a>b )[0]
方法二,Math的max和min方法调用
var arr = [1,4,6,2,33,19,6,9]; var maxvalue = Math.max.apply(null,arr); //33 var minvalue = Math.min.apply(null,arr); //1
在不用系统自带的sort的状况下对数组排序有不少方法,好比冒泡、插入以及快速排序等。但我总以为这些排序方法仍是过于复杂,有没有更快以及更方便的排序,我思考了很久,后来先想到了能够用数组的序号进行排序。原理是把数组1中的值变成数组2中的序号:
var arr = [3,4,6,2,8,7,5], arr2 = []; arr.forEach(item => arr2[item] = item); arr = []; arr2.forEach(item => arr.push(item));
写完以后本身感受美滋滋,可以后发现若是数组中有负数,不就都玩完了吗。因而赶忙改:
var arr = [3,-4,6,-2,-8,7,5], parr = []; narr = []; arr.forEach(item => item>=0?parr[item] = item:narr[-item] = item); arr = []; parr.forEach(item => arr.push(item)); narr.forEach(item => arr.unshift(item));
注:若是数组中有重复数字则排序方法有误,会把重复数字去掉。
写完以后发现其实也没有比冒泡、插入以及快速排序的方法快多少。
一开始我想到一个方法,把两个数组转换成字符串,在进行includes或者indexOf判断就能够了,后来我发现了问题:
var a = [2,4,8,6,12,67,9]; var b = [8,6,12]; a.join(',').includes(b.join(',')); //true; 这是能够的 var b = [8,6,1] a.join(',').includes(b.join(',')); //true; 这竟然也能够,显然有问题 //因而改为 a.join(',').includes(','+b.join(',')+','); //false; //后来我又发现若是b数组在a数组的开头和结尾都会有问题,因而又改为以下: (','+a.join(',')+',').includes(','+b.join(',')+','); //false;
写这篇文章主要是对本身学习数组作一个总结。若是对上面的问题有更好的解答,欢迎留言告知。