序言
javaScript的数组对象是我们在实际开发中经常用到的,so以此总结来增加印象,顺便提了几个容易误区的点。
一、常用方法一(改变自身)
1.Array.pop()
pop() 方法删除一个数组中的最后的一个元素,并且返回这个元素,改变原来数组,后进先出的出栈过程
var arr = [1, 2, 3, 4, 5]
arr.pop()
console.log(arr) // 1,2,3,42.Array.push()
方法添加一个或者多个元素到数组末尾,并且返回数组新的长度,改变原来数组。入栈的过程
var arr = [1, 2, 3, 4, 5]
arr.push(6, 7)
console.log(arr) // 1,2,3,4,5,6,73.Array.unshift()
方法用于在数组开始处插入一些元素(就像是栈底插入),并返回数组新的长度。
var arr = [1, 2, 3, 4, 5]
arr.unshift(6, 7)
console.log(arr) // 6,7,1,2,3,4,54.Array.shift()
shift()方法删除数组的第一个元素,并返回这个元素。出栈过程
var arr = [1, 2, 3, 4, 5]
arr.shift()
console.log(arr) // 2,3,4,55.Array.splice()
splice()方法用新元素替换旧元素的方式来修改数组。它是一个常用的方法,复杂的数组操作场景通常都会有它的身影,特别是需要维持原数组引用时,就地删除或者新增元素,splice是最适合的。
start 指定从哪一位开始修改内容。如果超过了数组长度,则从数组末尾开始添加内容;如果是负值,则其指定的索引位置等同于 length+start (length为数组的长度),表示从数组末尾开始的第 -start 位
deleteCount 指定要删除的元素个数,若等于0,则不删除。这种情况下,至少应该添加一位新元素,若大于start之后的元素总和,则start及之后的元素都将被删除。
itemN 指定新增的元素,如果缺省,则该方法只删除数组元素。
返回值 由原数组中被删除元素组成的数组,如果没有删除,则返回一个空数组。
var arr = ["a","b","c"];
var splices = arr.splice(1,1);
console.log(arr); // ["b","c"]
console.log(splices); // ["a"] 可见是从数组下标为1的元素开始删除,并且删除一个元素,由于itemN缺省,故此时该方法只删除元素
var arr = ["a","b"];
var splices = arr.splice(2,1,"d");
console.log(arr); // ["a", "b", "d"]
console.log(splices); // [], 可见由于start超过数组长度,此时从数组末尾开始添加元素,并且原数组不会发生删除行为
var array = ["apple","boy"];
var splices = array.splice(-2,1,"cat");
console.log(array); // ["cat", "boy"]
console.log(splices); // ["apple"], 可见当start为负值时,是从数组末尾开始的第-start位开始删除,删除一个元素,并且从此处插入了一个元素
var array = ["apple","boy"];
splices = array.splice(-3,1,"cat");
console.log(array); // ["cat", "boy"]
console.log(splices); // ["apple"], 可见即使-start超出数组长度,数组默认从首位开始删除
var array = ["apple","boy"];
splices = array.splice(0,3,"cat");
console.log(array); // ["cat"]
console.log(splices); // ["apple", "boy"], 可见当deleteCount大于数组start之后的元素总和时,start及之后的元素都将被删除
6.Array.reverse()
reverse()方法颠倒数组中元素的位置,第一个会成为最后一个,最后一个会成为第一个,该方法返回对数组的引用。
var array = [1,2,3,4,5];
var array2 = array.reverse();
console.log(array); // [5,4,3,2,1]
console.log(array2===array); // true7.Array.sort()
sort()方法对数组元素进行排序,并返回这个数组。sort方法比较复杂,这里我将多花些篇幅来讲这块。
var array = ["1","3","4","2"];
var array2 = array.sort(function(a,b){
return a > b
});
console.log(array);
console.log(array2 == array); // true
//如果缺省,数组元素将按照各自转换为字符串的Unicode(万国码)位点顺序排序
array = [10, 1, 3, 20];
var array3 = array.sort();
console.log(array3); // [1, 10, 20, 3]补充小知识--类数组对象转换数组,即 鸭式变形
var o = {0:"cat", 1:"dog", 2:"cow", 3:"chicken", 4:"mouse", length:5}
var item = Array.prototype.pop.call(o); // 重点
console.log(o); // Object {0: "cat", 1: "dog", 2: "cow", 3: "chicken", length: 4}
console.log(item); // mouse二、常用方法二(不改变自身)
1.Array.concat()
concat() 方法将传入的数组或者元素与原数组合并,组成一个新的数组并返回。
var array = [1, 2, 3];
var array2 = array.concat(4,[5,6],[7,8,9]);
console.log(array2); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(array); // [1, 2, 3], 可见原数组并未被修改
// 若concat方法中不传入参数,那么将基于原数组浅复制生成一个一模一样的新数组(指向新的地址空间)
var array = [{a: 1}];
var array3 = array.concat();
console.log(array3); // [{a: 1}]
console.log(array3 === array); // false
console.log(array[0] === array3[0]); // true,新旧数组第一个元素依旧共用一个同一个对象的引用
补充小点
push()方法与concat() 的时间复杂度谁的高?
push()函数是会修改原有的数组数据,执行push()方法后原有数组的值会对应的改变;而concat()方法则是先把原数组原封不动的复制到一个新的数组,然后在新数组上进行操作,所以concat()不会改变原数组的值。
2.Array.join()
join() 方法将数组中的所有元素连接成一个字符串。
var array = ['We', 'are', 'Chinese'];
console.log(array.join()); // "We,are,Chinese"
console.log(array.join('+')); // "We+are+Chinese"
console.log(array.join('')); // "WeareChinese"3.Array.slice()
slice() 方法将数组中一部分元素浅复制存入新的数组对象,并且返回这个数组对象。
参数 start 指定复制开始位置的索引,end如果有值则表示复制结束位置的索引(不包括此位置)。
如果 start 的值为负数,假如数组长度为 length,则表示从 length+start 的位置开始复制,此时参数 end 如果有值,只能是比 start 大的负数,否则将返回空数组。
var array = ["one", "two", "three","four", "five"];
console.log(array.slice()); // ["one", "two", "three","four", "five"]
console.log(array.slice(2,3)); // ["three"]4.Array.toString()
toString() 方法返回数组的字符串形式,该字符串由数组中的每个元素的 toString() 返回值经调用 join() 方法连接(由逗号隔开)组成。
语法:arr.toString()
var array = ['Jan', 'Feb', 'Mar', 'Apr'];
var str = array.toString();
console.log(str); // Jan,Feb,Mar,Apr5.Array.indexOf()
indexOf() 方法用于查找元素在数组中第一次出现时的索引,如果没有,则返回-1
语法:arr.indexOf(element, fromIndex=0)
element 为需要查找的元素。
fromIndex 为开始查找的位置,缺省默认为0。如果超出数组长度,则返回-1。如果为负值,假设数组长度为length,则从数组的第 length + fromIndex项开始往数组末尾查找,如果length + fromIndex<0 则整个数组都会被查找。
indexOf使用严格相等(即使用 === 去匹配数组中的元素)。
var array = ['abc', 'def', 'ghi','123'];
console.log(array.indexOf('def')); // 1
console.log(array.indexOf('def',-1)); // -1 此时表示从最后一个元素往后查找,因此查找失败返回-1
console.log(array.indexOf('def',-4)); // 1 由于4大于数组长度,此时将查找整个数组,因此返回1
console.log(array.indexOf(123)); // -1, 由于是严格匹配,因此并不会匹配到字符串'123'6.Array.lastIndexOf()
lastIndexOf() 方法用于查找元素在数组中最后一次出现时的索引,如果没有,则返回-1。并且它是indexOf的逆向查找,即从数组最后一个往前查找。
语法:arr.lastIndexOf(element, fromIndex=length-1)
element 为需要查找的元素。
fromIndex 为开始查找的位置,缺省默认为数组长度length-1。如果超出数组长度,由于是逆向查找,则查找整个数组。如果为负值,则从数组的第 length + fromIndex项开始往数组开头查找,如果length + fromIndex<0 则数组不会被查找。
同 indexOf 一样,lastIndexOf 也是严格匹配数组元素。
7.includes(ES7新增)
includes() 方法基于ECMAScript 2016(ES7)规范,它用来判断当前数组是否包含某个指定的值,如果是,则返回 true,否则返回 false。
语法:arr.includes(element, fromIndex=0)
element 为需要查找的元素。
fromIndex 表示从该索引位置开始查找 element,缺省为0,它是正向查找,即从索引处往数组末尾查找。
var array = [-0, 1, 2];
console.log(array.includes(+0)); // true
console.log(array.includes(1)); // true
console.log(array.includes(2,-4)); // true以上,includes似乎忽略了 -0 与 +0 的区别,这不是问题,因为JavaScript一直以来都是不区分 -0 和 +0 的。
补充小点indexOf()和 includes()的区别
曾经一次面试,面试官给我写了一段下面,问我这段代码会有什么问题,问的我一脸懵逼,经常这么用没什么问题啊,后来他提示我 数字有一种类型是不等于自己的 ,这我才明白过来,是NaN, 如果下面代码 arr 数组里面有NaN的话,那这行代码就不准确了。所以es7出了个includes() 的api。
if(arr.indexOf(x)>-1) {}这就是他们最直观的区别,includes能够发现NaN,而indexOf不能。
var array = [1,2,NaN];
console.log(array.includes(NaN)); // true
console.log(arra.indexOf(NaN)>-1); // false三、常用方法三(遍历)
1. Array.forEach()
forEach() 方法指定数组的每项元素都执行一次传入的函数,返回值为undefined。
语法:arr.forEach(fn, thisArg)
fn 表示在数组每一项上执行的函数,接受三个参数:
- value 当前正在被处理的元素的值
- index 当前元素的数组索引
- array 数组本身
thisArg 可选,用来当做fn函数内的this对象。
forEach 将为数组中每一项执行一次 fn 函数,那些已删除,新增或者从未赋值的项将被跳(但不包括值为 undefined 的项)。
var array = [1, 3, 5];
var obj = {name:'cc'};
var sReturn = array.forEach(function(value, index, array){
array[index] = value * value;
console.log(this.name); // cc被打印了三次
},obj);
console.log(array); // [1, 9, 25], 可见原数组改变了
console.log(sReturn); // undefined, 可见返回值为undefined2.Array.map()
map() 方法遍历数组,使用传入函数处理每个元素,并返回函数的返回值组成的新数组。
语法:arr.map(fn, thisArg)
参数介绍同 forEach 方法的参数介绍。
补充小点forEach() 和 map()的区别
forEach没有返回值,可以改变原来数组。
map()会返回一个新的数组,但不会改变原来数组
3.Array.filter()
filter() 方法使用传入的函数测试所有元素,并返回所有通过测试的元素组成的新数组。它就好比一个过滤器,筛掉不符合条件的元素。
语法:arr.filter(fn, thisArg)
var array = [18, 9, 10, 35, 80];
var array2 = array.filter(function(value, index, array){
return value > 20;
});
console.log(array2); // [35, 80]4.Array.reduce() Array.reduceRight()
reduce() 方法接收一个方法作为累加器,数组中的每个值(从左至右) 开始合并,最终为一个值。
reduceRight() 方法接收一个方法作为累加器,数组中的每个值(从右至左)开始合并,最终为一个值。除了与reduce执行方向相反外,其他完全与其一致,请参考上述 reduce 方法介绍。
语法:arr.reduce(fn, initialValue)
fn 表示在数组每一项上执行的函数,接受四个参数:
- previousValue 上一次调用回调返回的值,或者是提供的初始值
- value 数组中当前被处理元素的值
- index 当前元素在数组中的索引
- array 数组自身
initialValue 指定第一次调用 fn 的第一个参数。
当 fn 第一次执行时:
- 如果 initialValue 在调用 reduce 时被提供,那么第一个 previousValue 将等于 initialValue,此时 item 等于数组中的第一个值;
- 如果 initialValue 未被提供,那么 previousVaule 等于数组中的第一个值,item 等于数组中的第二个值。此时如果数组为空,那么将抛出 TypeError。
- 如果数组仅有一个元素,并且没有提供 initialValue,或提供了 initialValue 但数组为空,那么fn不会被执行,数组的唯一值将被返回。
var array = [1, 2, 3, 4];
var s = array.reduce(function(previousValue, value, index, array){
return previousValue * value;
},1);
console.log(s); // 24
// ES6写法更加简洁
array.reduce((p, v) => p * v); // 24| callback | previousValue | currentValue | index | array | return value |
|---|---|---|---|---|---|
| 第1次 | 1 | 1 | 0 | [1,2,3,4] | 1 |
| 第2次 | 1 | 2 | 1 | [1,2,3,4] | 2 |
| 第3次 | 2 | 3 | 2 | [1,2,3,4] | 6 |
| 第4次 | 6 | 4 | 3 | [1,2,3,4] | 24 |
5.Array.every()
every() 方法使用传入的函数测试所有元素,只要其中有一个函数返回值为 false,那么该方法的结果为 false;如果全部返回 true,那么该方法的结果才为 true。
var arr = [10,8,20,15,16]
var bool = arr.every(function(value, index, obj){
return value >= 8;
});
console.log(bool); // true6.Array.some()
some() 方法刚好同 every() 方法相反,some 测试数组元素时,只要有一个函数返回值为 true,则该方法返回 true,若全部返回 false,则该方法返回 false。
var arr = [10,8,20,15,16]
var bool = arr.every(function(value, index, obj){
return value > 15;
});
console.log(bool); // true7.Array.find() Array.findIndex()
find() 方法基于ECMAScript 2015(ES6)规范,返回数组中第一个满足条件的元素(如果有的话), 如果没有,则返回undefined。
findIndex() 方法也基于ECMAScript 2015(ES6)规范,它返回数组中第一个满足条件的元素的索引(如果有的话)否则返回-1。
语法:arr.find(fn, thisArg),
我们发现它们的语法与forEach等十分相似,其实不光语法,find(或findIndex)在参数及其使用注意事项上,均与forEach一致。因此此处将略去 find(或findIndex)的参数介绍。下面我们来看个例子
var array = [1, 3, 5, 7, 8, 9, 10];
function f(value, index, array){
return value%2==0; // 返回偶数
}
function f2(value, index, array){
return value > 20; // 返回大于20的数
}
console.log(array.find(f)); // 8
console.log(array.find(f2)); // undefined
console.log(array.findIndex(f)); // 4
console.log(array.findIndex(f2)); // -18.Array.entries()
9.Array.keys()
10.Array.values()
四、ES6新增的构造函数方法
1.Array.from()
用于把两类对象转化成真的数组:
a.类似数组的的对象(就是任何有length属性的对象);
b.可遍历的对象;
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};
// ES5的写法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']
// ES6的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']第二个参数 有map 的功能
Array.from(arrayLike, x => {x * x })
//等同于
Array.from(arrayLike).map(x => x * x);
第三个参数可以绑定 this
如果map函数里面用到了this关键字,还可以传入Array.from的第三个参数,用来绑定this
var y = 1
Array.from(arrayLike, x => {x * y }, window)2. Array.of()
方法用于将一组值转化为数组
Array.of(1,2,3,4) //[1,2,3,4]
Array.of(3) // [3]
Array.of(3).length // 1这个方法的主要目的,是弥补数组构造函数Array()的不足。因为参数个数的不同,会导致Array()的行为有差异。
Array() // []
Array(3) // [, , ,]
Array(3, 11, 8) // [3, 11, 8]Array.of基本上可以用来替代Array()或new Array(),并且不存在由于参数不同而导致的重载。它的行为非常统一。
Array.of() // []
Array.of(undefined) // [undefined]
Array.of(1) // [1]
Array.of(1, 2) // [1, 2]
Array.of总是返回参数值组成的数组。如果没有参数,就返回一个空数组。
Array.of方法可以用下面的代码模拟实现。
function ArrayOf(){
return [].slice.call(arguments);
}3.Array.find()
用于查找第一个符合条件的数组成员。直到找出第一个返回值为true的成员,然后返回改成员。如果没有返回条件的成员,则返回undefined
4.Array.findIndex()
与find方法相同,找不到放回-1
[NaN].findIndex(y => Object.is(NaN, y))5.Array.fill()
fill方法使用给定的值,填充一个数组
['a', 'b', 'c'].fill(7)
// [7, 7, 7]
new Array(3).fill(7)
// [7, 7, 7]fill方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。
['a', 'b', 'c'].fill(7, 1, 2)
// ['a', 7, 'c']五、判断方法
Array.isArray([])
判断是都是数组,不多讲了