JS—数组方法总结
1、(1)push(): 向数组尾部添加一个或多个元素,并返回添加新元素后的数组长度。注意,该方法会改变原数组。
1 var arr1 = [10111, 1101, 111];
2 console.log(arr1.push(100));//4 返回数组长度
3 console.log(arr1);//[10111, 1101, 111, 100]
(2)pop(): 删除数组的最后一个元素,并返回该元素。注意,该方法会改变原数组。
2、(1)shift():删除数组的第一个元素,并返回该元素。注意,该方法会改变原数组。
shift()还可以用于遍历并清空数组。
1 var arr2 = [1,2,4,7,10]; 2 var item; 3 while(item = arr2.shift()){ 4 console.log(item) 5 } 6 console.log(arr2);//[]
(2)unshift():在数组的第一个位置添加元素,并返回添加新元素后的数组长度。注意,该方法会改变原数组。
3、valueOf():返回数组本身。
1 var arr2 = [1,2,4,7,10]; 2 console.log(arr2.valueOf());//[1,2,4,7,10]
4、indexOf():返回指定元素在数组中出现的位置,如果没有出现则返回-1
。还可以接受第二个参数,表示搜索的开始位置。(也可以用于字符串)
5、toString():返回数组的字符串形式。
1 var arr1 = [10111, 1101, 111]; 2 console.log(arr1.toString());//"10111,1101,111" 3 var arr2 = [1,2,4,7,[1,2,3]]; 4 console.log(arr2.toString());//"1,2,4,7,1,2,3"
6、join():以参数作为分隔符,将所有数组成员组成一个字符串返回。如果不提供参数,默认用逗号分隔。
7、concat():用于多个数组的合并。它将新数组的成员,添加到原数组的尾部,然后返回一个新数组,原数组不变。(也可以用于字符串)
8、reverse():用于颠倒数组中元素的顺序,返回改变后的数组。注意,该方法将改变原数组。
9、slice():用于截取原数组的一部分,返回一个新数组,原数组不变。(也可以用于字符串)
10、splice():删除原数组的一部分成员,并可以在被删除的位置添加入新的数组成员,返回值是被删除的元素。注意,该方法会改变原数组。
(1)splice(start,delNum,addElement1,addElement2,...)第一个参数是删除的起始位置,第二个参数是被删除的元素个数。如果后面还有更多的参数,则表示这些就是要被插入数组的新元素。
(2)如果只插入元素,第二个参数可以设为0;
(3)起始位置如果是负数,就表示从倒数位置开始删除;
11、sort():对数组成员进行排序,默认是按照字典顺序排序。排序后,原数组将被改变。
(1)需要特殊注意。sort
方法不是按照大小排序,而是按照对应字符串的字典顺序排序。也就是说,数值会被先转成字符串,再按照字典顺序进行比较,所以101
排在11
的前面。
(2)想让sort
方法按照自定义方式排序,可以传入一个函数作为参数,表示按照自定义方法进行排序。该函数本身又接受两个参数,表示进行比较的两个元素。如果返回值大于0
,表示第一个元素排在第二个元素后面,即从小到大;其他情况下,都是第一个元素排在第二个元素前面。
12、map():对数组的所有成员依次调用一个函数,根据函数结果返回一个新数组。
13、filter():参数是一个函数,所有数组成员依次执行该函数,返回结果为true
的成员组成一个新数组返回。该方法不会改变原数组。
ES6—数组相关方法
1、扩展运算符——spread,是三个点(...),将一个数组变换为用逗号分隔的参数序列;
(1)扩展运算符后面是一个空数组,将不产生任何效果;
(2)主要用于函数的调用;(作为函数参数)
(3)...后面可以放置表达式
var arr = [ ...(2 > 3 ? [4,5,6]:[1,2,3]) ,100 ]; console.log(arr);//[1, 2, 3, 100]
(4)代替apply()方法
- 将数组转换为函数的参数
1 function f5(x,y,z) {console.log(x+y+z)} 2 var arr = [1,2,3]; 3 f5.apply(null,arr);//6 4 f5(...arr);//6
说明:apply()方法与call()、bind()方法用于改变this的指示方向。区别:
a. apply()与call()区别:函数参数传递方式不同,call传入参数列表,apply将参数以数组形式传入;
b. call()与bind()区别:bind()返回一个函数,需要再调用一次
- 求数组的最大值
1 //求一个参数序列的最大值 2 console.log(Math.max(1,2,4,100));//100 3 //求一个数组的最大值 4 console.log(Math.max.apply(null,[1,2,4,100]));//100 5 console.log(Math.max(...[1,2,4,100]));//100
扩展运算符的应用:
(1)复制数组、组合数组
var arr1 = [1,2,3]; var arr2 = [4,5,6]; //复制 console.log(arr1.concat());[1, 2, 3] console.log([...arr1]);[1, 2, 3] //组合 console.log(arr1.concat(arr2));[1, 2, 3, 4, 5, 6] console.log([...arr1,...arr2]);[1, 2, 3, 4, 5, 6]
说明:以上两种方法,都是浅拷贝,新数组的成员都是对原数组成员的引用,如果修改了引用指向的值(即原数组成员对象的值),会同步反映到新数组。
(2)与解构赋值组合,生成新数组;扩展运算符只能放在参数的最后一位,否则会报错。
(3)运用于字符串,生成字符串数组,能够正确识别四个字节的 Unicode 字符。
(4)任何定义了遍历器(Iterator)接口的对象,都可以用(...)转为真正的数组,如Map和Set结构,Generator 函数。对于那些没有部署 Iterator 接口的类似数组的对象,(...)就无法将其转为真正的数组,便会报错。
2、Array.from():用于将两类对象转为真正的数组:类似数组的对象和可遍历的对象(包括ES6新增的数据结构Set和Map)。
(1)任何有length
属性的对象,都可以通过Array.from
方法转为数组,而此时扩展运算符就无法转换。
(2)Array.from
还可以接受第二个参数,作用类似于数组的map
方法,用来对每个元素进行处理,将处理后的值放入返回的数组。
1 function typesOf () { 2 return Array.from(arguments, value => typeof value) 3 } 4 typesOf(null, [], NaN) 5 // ['object', 'object', 'number']
1 Array.from({ length: 2 }, () => 'jack') 2 // ['jack', 'jack']
(3)将字符串转换为数组,并返回字符串的长度。
Array.from(string).length
3、Array.of():用来替代Array()与new Array()方法,不存在由于参数不同导致的重载,行为十分统一。总是返回由参数值组成的数组,无参数则返回空数组。
不像Array()与new Array(),这两个方法,无参数返回空数组;一个参数,参数值指代新数组的长度;两个及两个以上参数,返回由参数组成分数组。
Array.of()方法的模拟代码实现: function ArrayOf(){ return [].slice.call(arguments); } function ArrayOf(){ return Array.prototype.slice.call(arguments); }
4、copyWithin(target,start,end):将start到end(不包括)位置的元素,从target位置开始粘贴覆盖。
// 对于没有部署 TypedArray 的 copyWithin 方法的平台 // 需要采用下面的写法 [].copyWithin.call(new Int32Array([1, 2, 3, 4, 5]), 0, 3, 4); // Int32Array(5) [4, 2, 3, 4, 5]
5、find()与findIndex():返回第一个符合条件的数组成员/成员索引,没有符合条件的,则返回undefined/-1。
(1)接收两个参数,第一个参数是回调函数,回调函数有三个参数,依次为当前值,当前值的索引,原数组。
第二个参数是绑定回调函数的this对象。(person)
function f(v){ return v > this.age; } let person = {name: 'John', age: 20}; [10, 12, 26, 15].find(f, person); // 26
(2)以上两种方法都可以发现数组中的NAN,弥补了indexOf()方法的不足。
[NaN].indexOf(NaN) //-1 [NaN].findIndex(ele => Object.is(ele,NaN)) //0
说明:==与===与Object.is(val1,val2),===严格比较运算符,类型相同,值相等,引用物理地址必须相等。
===与Object.is(val1,val2)的区别:行为基本一致。除了+0与-0,NaN。
a. +0===-0,true ##### NaN===NaN,false(NaN不与任何值相等,包括他自己)
b. Object.is(+0,-0),false ##### Object.is(NaN,NaN),true
6、fill(val,start,end)方法:使用给定的值,填充数组的[start,end)位置。多用于初始化空数组。
new Array(3).fill(7) //[7,7,7]
说明:填充的类型为对象,那么被赋值的是同一个内存地址的对象,而不是深拷贝对象。
7、ES6 提供三个新的方法——entries()
,keys()
和values()
——用于遍历数组。它们都返回一个遍历器对象,可以用for...of
循环进行遍历,唯一的区别是keys()
是对键名的遍历、values()
是对键值的遍历,entries()
是对键值对的遍历。如果不使用for...of
循环,可以手动调用遍历器对象的next
方法,进行遍历。
8、includes()方法:用于判断数组是否包含给定的值,与String类型的includes()方法类似。可以识别NaN。
(1)包含两个参数(ele,开始搜索位置),参数2默认为0。
(2)该方法之前通过(arr.indexOf(ele) !== -1)来判断一个数组是否包含某元素。缺点1:不够语义化,表达起来不够直观。缺点2:indexOf()内部使用(===)严格相等依次进行比较,会导致对NaN的误判。
(3)下面代码用来检查当前环境是否支持该方法,如果不支持,部署一个简易的替代版本。
const contains = (() => Array.prototype.includes ? (arr, value) => arr.includes(value) : (arr, value) => arr.some(el => el === value) )(); contains(['foo', 'bar'], 'baz'); // => false
(4)Map 和 Set 数据结构有一个has
方法,需要注意与includes
区分。Map 结构的has
方法,是用来查找键名的,Set 结构的has
方法,是用来查找值的。
9、数组扁平化flat()、flatMap()
(1)数组扁平化flat():将嵌套的数组“拉平”,变成一维数组,产生一个新数组,对原数组没有改变。
- flat()默认拉平一层,flat(n)则拉平n层,flat(Infinity)则拉平至一维;
- 若原数组有空位,flat()会跳过空位(忽略)。
(2)flatMap(遍历函数,obj):对数组的每一个成员执行一次map()函数,再对产生的新数组执行flat()函数。该方法只能展开一层。
参数2绑定遍历函数里面的this。
10、插入排序、合并排序、冒泡排序等都是稳定的,堆排序、快速排序等是不稳定的。不稳定排序的主要缺点是,多重排序时可能会产生问题。
ES2019 明确规定,Array.prototype.sort()
的默认排序算法必须稳定。这个规定已经做到了,现在 JavaScript 各个主要实现的默认排序算法都是稳定的。