JavaScript数组

array

基本操作

创建数组

1
2
3
4
5
6
//数组实例的创建
var arr = [];
var arr = new Array();//创建空数组
var arr = new Array(5);//创建一个length值为5的数组[undefined]

var arr = Array.of(1,2,3);//创建数组并赋值[1,2,3]

检测数组

1
2
3
4
5
6
7
8
9
10
11
12
   //判断是否是数组
/*<!-- 方法一 -->*/
arr instanceof Array;

/*<!-- 方法二 -->*/
Object.prototype.toString.call(arr);//[object Array]

/*<!-- 方法三 -->*/
Array.isArray(arr);

/*<!-- 方法四 -->*/
arr.constructor == Array;

数组方法

Array.isArray(obj)

检测对象是否是Array,是(true),否(false)。

Array.from(arrayLike,mapFn,thisArg)

将一个类数组或可迭代对象转换为新的数组。参数arrayLike是转换项,mapFn是可选参数,如果指定了该参数,则生成的数组会经过该函数的加工后再返回。thisArg是可选参数,为执行mapFn函数时this的值。

只要有length属性,就可以算作类数组

常见的类数组对象包括DOM操作返回的NodeList集合,以及函数内部的arguments对象。

注意:对象的length属性必须写明,且键名必须是数字。

1
2
3
4
5
6
7
8
9
10
11
12
13
   const arrayLike = {
0 : 'a',
1 : 'b',
2 : 'c',
length:3
};
const str = 'ace';
const arrayLike2 = {length : 5};

const newArray = Array.from(arrayLike);
const newArray2 = Array.from(arrayLike,(v) => v+'1');
const newArray3 = Array.from(arrayLike2);
const newArray3 = Array.from(str);// ['a','c','e'] 因为字符串也有length属性

Array.of(item…)

该方法用于创建数组实例。与Array构造函数区别在于处理整数参数:Array.of(3)创建一个具有单个元素3的数组,而Array(3)创建length为3,包含3个undefined的数组。

1
2
3
4
5
   Array.of(3); //[3]
Array.of(1,2,3); //[1,2,3]

Array(3); //[,,]
Array(1,2,3); //[1,2,3]

数组实例方法

转换方法 arr.join(separator)

把数组转换为字符串,在使用分隔符连接在一起,默认参数是逗号”,”。空字符串表示无间隔。

1
2
3
   const arr = [1,2,3,4,5];
arr.join("|");//"1|2|3|4|5"
arr.join("");//1,2,3,4,5

栈方法 push,pop

arr.push(item…)

将一个或多个新元素添加到数组的末尾,并返回数组的新长度。

arr.pop()

删除数组的最后一项,并返回该项。

队列方法 unshift,shift

arr.unshift()

将一个或多个元素添加到数组的头部,并返回数组的行长度。

arr.shift()

删除数组的第一项,并返回该项。如果数组是空的,它会返回undefined。

重排序方法 reverse,sort

arr.reverse()

反转数组的顺序。并且会改变原数组的内容。

arr.sort(compareFn)

sort默认会使用Unicode顺序来排序,所以对数组并不会按照大小顺序排序。传入一个比较函数,该方法接受两个参数。

1
2
   var arr = [12,5,54];
arr.sort((a,b) => a-b);

操作方法 concat,slice,splice

arr.concat(item…)

保留数组arr的副本,并将多个数组附加在其后连接为一个数组,返回新的数组。

arr.slice(start,end)

不包括end对应的元素,截取从[start,end)的数组元素。

arr.splice(start,deleteCount,item)

该方法会修改原数组。从arr中移除一个或多个元素,并将新的item插入至移除元素的开始位置。参数分别为(开始位置,移除元素个数,一个或多个插入元素)。

位置方法 indexOf,lastIndexOf,includes

arr.indexOf(searchElement,start)

返回要查找的项在数组中的位置,如果没有找到则返回-1。接收两个参数。(查找项,查找起始位置索引值)。

arr.lastIndexOf(searchElement,start)

indexOf的逆向查找方式。从start位置向前查找。这两种查找方式都使用全等( === )操作符,所以不能查找NaN。

arr.includes(searchElement,fromIndex)

判断当前数组是否包含指定的值,是则返回true,否则返回false。includes()方法内部的比较方法是:”SameValueZero”。该方法可以搜索NaN值。

1
2
[12,5,54,'2k','2d'].includes(5,1);
[1,2,NaN].includes(NaN);//true

迭代方法 every,some,filter,forEach,map,find,entries,keys,values

arr.every(callback,thisArg)

对数组的每一项运行给定参数,如果该函数对每一项都返回true,则返回true。callback被调用时传入三个参数:元素值,元素的索引,原数组。thisArg为可选参数,指定执行callback时使用this值。

arr.some(callback,thisArg)

对数组中的每一项运行给定函数,如果该函数对任意一项返回true,则返回true。

arr.filter(callback,thisArg)

对数组每一项运行给定函数,返回函数会返回true的项组成的数组。

arr.forEach(callback)

本质上与for循环迭代数组一样。没有返回值。

arr.map(callback)

对数组中的每一项运行给定函数,返回每次函数调用组成的数组。

arr.find(callback,thisArg)

对数组所有成员依次执行callback函数,找出第一个返回值为true的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined。

1
[1,3,4,9].find((value,index,arr) => value>5);//9
arr.entries()
arr.keys()
arr.values()

以上三个方法都返回一个新的Array Iterator对象,可以使用for...of循环进行遍历,区别是keys是对键名的遍历,values是对键值的遍历,entries是对键值对的遍历。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
   for(let prop of ['a','b'].keys()){
console.log(prop);// 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'
}

let arr = ["a", "b"];
let iterator = arr.entries(); // undefined
console.log(iterator); // Array Iterator {}
console.log(iterator.next().value); // [0, "a"]
console.log(iterator.next().value); // [1, "b"]

归并方法 reduce,reduceRight

arr.reduce(callback,initialValue)
arr.reduceRight(callback,initialValue)

这个两个方法都会迭代数组所有的项,然后返回一个最终值。reduce()方法从数组的第一项开始,逐个遍历到最后,而reduceRight()则从数组的最后一项开始,向前遍历到第一项。

它们接受两个参数,callback 每一项上调用的函数,callback 被调用时传入四个参数:上一次调用回调返回的值、正在处理的元素、正在处理的元素的索引值、原数组。initialValue 是可选项,作为归并基础的初始值,其值用于第一次调用 callback 的第一个参数。

数组常见问题

数组合并

多个一维数组合并

两个一维数组,要将他们合并成一个数组:

  1. Array.prototype.concat()方法
1
2
3
const arr1 = [1, 2];
const arr2 = [3, 4];
const arr = arr1.concat(arr2) //[1, 2, 3, 4]
  1. for循环和Array.prototype.push()
1
2
3
4
5
6
7

function flation(arr1, arr2) {
for (let i = 0; i < arr2.length; i++) {
arr1.push(arr2[i]);
}
return arr1;
}

多维(复合)数组合并成一维数组

1
2
3
4
5
6
   var myArray = [
[1, 2],
[3, 4, 5],
[6, 7, 8, 9],
[11,12,[12,13,[14]]],10,11
];
  1. Array.prototype.push()方法
    使用了递归,所以可以合并二维数组以上的数组。
1
2
3
4
5
6
7
8
9
10
11
12
   function flatten(arr,result){
if(!result) result = [];
for(var i = 0;i < arr.length;i++){
if(arr[i].constructor == Array){
flatten(arr[i],result);
}else{
result.push(arr[i]);
}
}
return result;
}
console.log(flatten(myArray));
  1. Function.prototype.apply()
1
2
3
4
//省略对二维以上数组的判断
function flatten(arr){
return [].concat.apply([],arr);
}

如果需要处理多维数组,需要加一些判断,同样需要用到递归:

1
2
3
4
function flatten(arr){
arr = [].concat.apply([],arr);
return arr.some(Array.isArray)?flatten(arr) : arr;
}

  1. 使用join()和split()
    返回的数组内都是字符串。
1
2
3
4
function flatten(arr){
return arr.join(",").split(',');
}
flatten(myArray);

数组去重

关于数组去重之前有一篇文章总结过:数组去重

数组随机排序

递归方法

从数组中随机取出一个元素放入新数组中,同时删除原数组中该值,递归重复至全部取出。

1
2
3
4
5
6
7
8
9
10
11
12
13
   function randomSort(arr,newArr){
var newArr = newArr || [];
if(arr.length == 1){
newArr.push(arr[0]);
return newArr;
}
var random = Math.ceil(Math.random() * arr.length) - 1;
newArr.push(arr[random]);
arr.splice(random,1);
return randomSort(arr,newArr);
}
console.log(randomSort([2,3,4,1,3,4,4,42,2]));
console.log(randomSort([2,3,4,1,3,4,4,42,2]));

随机交换数组内的元素

遍历数组,每次从i位置后元素随机挑一个放到i位置,将原i位置元素放至挑选元素原位置。

1
2
3
4
5
6
7
8
9
10
11
12
   Array.prototype.shuffle = function(){
var len = this.length,
arr = this.slice(0),
temp,index;
for(var i = 0;i<len;i++){
index = i + Math.floor(Math.random() * (len - i));
temp = arr[i];
arr[i] = arr[index];
arr[index] = temp;
}
return arr.slice(0);
};

取数组中最大值最小值

遍历比较法
  • 变量存放最大值,将数组中的第一个值赋值给变量;
  • 遍历数组与最大值比较,如果大于最大值,则将该值赋给最大值变量;
  • 遍历结束后,返回变量;
1
2
3
4
5
6
7
8
9
Array.prototype.max = function(){
let max = this[0];
this.forEach(function(value){
if(value>max){
max = value;
}
})
return max;
}
归并比较法

一次比较回调函数中参数prev与cur的大小,返回其中的较大值。

1
2
3
4
5
   Array.prototype.max = function(){
return this.reduce( (prev,cur) =>
prev > cur ? prev : cur
);
}
Math.max与Math.min方法
1
Math.max.apply(null,arr);

从数组中寻找元素并删除元素

arguments + indexOf + filter 遍历判断法
  • 通过arguments对象分别获取数组arr和指定要删除的元素,将指定元素转换成数组removeArgs;
  • 使用filter筛选出arr内与removeArgs内不相同的元素,筛选规则通过indexOf方法判断;
1
2
3
4
5
6
7
8
9
10
11
12
13

function destroyer(para){
let arr = arguments[0];
let removeArgs = [];
for(let i = 1;i<arguments.length;i++){
removeArgs.push(arguments[i]);
}
let isFalse = function(v){
return removeArgs.indexOf(v) === -1;
}
return arr.filter(isFalse);
}
destroyer([1,43,4,2,2,5],5,2);
slice() + set + filter 方法
  • 使用filter()筛选出 arr 内与 set 对象内不相同的元素,筛选规则通过 set 对象的has()方法判断;
1
2
3
4
function destroyer(arr, ...items) {
var removeArgs = new Set(items);
return arr.filter(v => !removeArgs.has(v));
}