写在前面
数组作为一个最基础的一维数据结构,在各种编程语言中充当着至关重要的角色,不深入了解数组,就不足以写好Javascript。随着React和Vue等MVVM框架的流行,数据更新的同时视图也会随之更新。开发者会用数组来进行数据的存储和各种增删改查等操作,从而实现对应前端视图层的更新。截止es7规范,数组总共包含33个标准api方法和一个非标准的api方法。
那么:
- 数组的构造器有哪几种?
- 哪些是改变自身值的方法?
- 哪些不是改变自身值的方法?
- 遍历方法有哪些?
Array构造器
Array构造器用于创建一个新的数组,通常推荐使用对象字面量的方式创建数组,但是也有对象字面量创建数组乏力的时候。比如说创建一个长度为6的空数组,使用字面量形式是无法实现的。
//使用Array构造器,可以自定义长度
const arr = Array(6);//[empty × 6]
//使用对象字面量形式
const arr1 = [];
arr1.length = 6;//6
在new Array(arg1,arg2,...)
参数长度为0或长度>=2时,传入的参数将按照顺序依次成为新数组的0至N项(参数为0时,返回空数组)。
在new Array(len)
当len不是数值时,处理如上所示,返回一个只包含len元素一项的数组;当len是数值时,len最大不能超过32位无符号整型,即需要小于2的32次方,否则将会抛出异常RangError。
const arr1 = new Array();//[]
const arr2 = new Array(18);//[empty × 18]
const arr3 = new Array("yichuan","onechuan");//["yichuan","onechuan"]
const arr4 = new Array("yichuan");//["yichuan"]
const arr5 = new Array(2020,2021);//[2020, 2021]
es6新增的构造方法:Array.of和Array.from。其中Array.of用的少些,Array.from更具有灵活性。
Array.of()
Array.of用于将参数依次转为数组中的一项,然后返回这个新数组,而不论这个参数是数字还是其它。
Array.of() 和 Array 构造函数之间的区别在于处理整数参数:Array.of(7) 创建一个具有单个元素 7 的数组,而 Array(7) 创建一个长度为7的空数组(注意:这是指一个有7个空位(empty)的数组,而不是由7个undefined组成的数组)。
Array.of(7); // [7]
Array.of(1, 2, 3); // [1, 2, 3]
Array(7); // [ , , , , , , ]
Array(1, 2, 3); // [1, 2, 3]
Array.from()
Array.from()的设计初衷是快速便捷地基于其它对象创建新数组,准确而言就是从一个类数组的可迭代对象中,创建一个新的数组实例。Array.from() 方法对一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。
Array.from(arrayLike[, mapFn[, thisArg]])
Array.from()可以输入三个参数:
- 类数组或可迭代对象,必选参数
- 加工函数,新生成的数组将会经过此函数的加工而返回,可选参数
- this的作用域,表示加工函数执行时的this指向的对象,可选参数 ```javascript const obj = { 0:”yichuan”, 1:”onechuan”, 2:”pingchuan”, length:3 }
Array.from(obj,function(value,index){ console.log(value,index,this,arguments.length); return value.repeat(3);//必须指定返回值,否则为undefined },obj)
![image.png](https://cdn.nlark.com/yuque/0/2021/png/22745085/1638698994238-3e8bdb35-0f59-46b4-a1a9-807acdf0c4c6.png#clientId=u4670c6fc-e471-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=29&id=ua4db5514&margin=%5Bobject%20Object%5D&name=image.png&originHeight=58&originWidth=1484&originalType=binary&ratio=1&rotation=0&showTitle=false&size=18790&status=done&style=none&taskId=ub1aa84d4-a06a-4bbe-a1df-a43486ff873&title=&width=742)<br />当不需要改变this的指向的话,可以将加工函数写成箭头函数形式。
```javascript
//string
Array.from("yichuan");//["y","i","c","h","u","a","n"]
//Set
Array.from(new Set(["yichuan","onechuan"]));//["yichuan","onechuan"]
//Map
Array.from(new Map([[1,"yichuan"],[2,"onechuan"]]));//[[1,"yichuan"],[2,"onechuan"]]
Array.isArray()
Array.isArray()是用来判断一个变量是否为数组类型的方法。这样用于进行数组判断的方法就有6种:
- 基于instanceof
- 基于constructor
- 基于Object.prototype.isPrototypeOf
- 基于getPrototypeOf
- 基于Object.prototype.toString
基于Array.isArray()
const arr = [];
//1.基于instanceof
console.log(arr instanceof Array);
//2.基于constructor
console.log(arr.construcot === Array);
//3.基于Object.prototype.isPrototypeOf
console.log(Array.prototype.isPrototypeOf(arr));
//4.基于getPrototypeOf
console.log(Object.getPrototypeOf(arr) === Array.prototype);
//5.基于Object.prototype.toString
console.log(Object.prototype.toString.call(arr)==="[object Array]");
//6.基于Array.isArray()
console.log(Array.isArray(arr));
可以优化下数组判断:
if(!Array.isArray){
Array.isArray = function(arg){
return Object.prototype.toString.call(arg) === "[object Array]";
}
}
数组
在Javascript中数组api根据是否改变自身的方法有:
改变自身的方法:pop、push、reverse、shift、sort、splice、unshift以及两个es6新增的方法copyWithin和fill
-
改变自身的方法
(1) Array.prototype.pop()
pop()从数组中删除最后一个元素,并返回该元素的值。此方法更改数组的长度。pop()可以和call()或apply()一起使用时,可应用在类似数组的对象上。
const arr = ["red","green","blue"];
console.log(arr.pop());//"blue"
(2) Array.prototype.push()
push() 方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度。push()可以和call()或apply()一起使用时,可应用在类似数组的对象上。
const arr = ["red","green","blue"];
console.log(arr.push("black"));//4
(3) Array.prototype.reverse()
reverse() 方法将数组中元素的位置颠倒,并返回该数组。数组的第一个元素会变成最后一个,数组的最后一个元素变成第一个。该方法会改变原数组,返回该数组的引用。
const arr = ["red","green","blue"];
console.log(arr.reverse());//["blue","green","red"]
(4) Array.prototype.shift()
shift() 方法从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。
const arr = ["red","green","blue"];
console.log(arr.shift());//"red"
(5) Array.prototype.sort()
sort()方法使用原地算法对数组的元素进行排序,并返回数组。默认排序顺序是将元素转换为字符串,然后比较它们的UTF-16代码单元值序列时构建的。无法保证排序的时间和空间复杂性。默认是从小到大排序。
const arr = [89,70,22,11,333];
console.log(arr.sort(arr));//[11,22,70,89,333]
当然,我们也可以对sort的函数sortFun()进行自定义对数组排序:
sortFun(a, b)<0,表示a可以排在b前;
- sortFun(a, b)=0,表示a和b的位置不变;
- sortFun(a, b)>0,表示a排在b后
sortFun()总是对相同的输入返回相同的比较结果,否则排序的结果将是不确定的。
const arr = [89,70,22,11,333];
console.log(arr.sort((x,y)=>x>y));//[333,89,70,22,11]
(6) Array.prototype.splice()
splice() 方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。
array.splice(startIndex,deleteCount,[item1,item2,...]);
Array.prototype.splice()可以输入三个参数:
- startIndex:指定修改的开始位置(从0计数)。如果超出了数组的长度,则从数组末尾开始添加内容;如果是负值,则表示从数组末位开始的第几位(从-1计数,这意味着-n是倒数第n个元素并且等价于array.length-n);如果负数的绝对值大于数组的长度,则表示开始位置为第0位。
- deleteCount:整数,表示要移除的数组元素的个数。
- deleteCount>startIndex之后元素的总数,则从startIndex开始后面的元素都将被删除(包含startIndex位)
- 如果deleteCount被省略了,或者它的值大于等于array.length - start(也就是说,如果它大于或者等于start之后的所有元素的数量),那么start之后数组的所有元素都会被删除。
- 如果 deleteCount <=0,则不移除元素。这种情况下,至少应添加一个新元素。
- [item1,item2,…]:是可选参数,要添加进数组的元素,从start 位置开始。如果不指定,则 splice() 将只删除数组元素。 ```javascript //删除指定索引后的元素 const arr = [“red”,”green”,”blue”]; console.log(arr.splice(2));//[“red”,”green”]
//要向数组中添加的元素 const arr = [“red”,”green”,”blue”]; console.log(arr.splice(1,[“black”,”brown”]));//[“red”,”black”,”brown”,”green”,”blue”]
<a name="lxTvm"></a>
#### (7) Array.prototype.unshift()
unshift() 方法将一个或多个元素添加到数组的开头,并返回该数组的新长度(该方法修改原有数组)。unshift 方法会在调用它的类数组对象的开始位置插入给定的参数。
```javascript
arr.unshift(element1, ..., elementN)
使用:
let arr = [4,5,6];
arr.unshift(1,2,3);
console.log(arr); // [1, 2, 3, 4, 5, 6]
(8) Array.prototype.copyWithin()
copyWithin() 方法浅复制数组的一部分到同一数组中的另一个位置,并返回它,不会改变原数组的长度。
arr.copyWithin(targetIndex, startIndex, endIndex);
arr.copyWithin()
可以输入三个参数:
- targetIndex:0 为基底的索引,复制序列到该位置。
- 如果是负数,targetIndex 将从末尾开始计算。
- 如果 targetIndex >= arr.length,将会不发生拷贝。
- 如果 targetIndex > startIndex,复制的序列将被修改以符合 arr.length。
- startIndex:0 为基底的索引,开始复制元素的起始位置。
- 如果是负数,startIndex将从末尾开始计算。
- 如果 startIndex 被忽略,copyWithin 将会从0开始复制。
- endIndex:0 为基底的索引,开始复制元素的结束位置。copyWithin 将会拷贝到该位置,但不包括 end 这个位置的元素。
- 如果是负数, end 将从末尾开始计算。
- 如果 end 被忽略,copyWithin 方法将会一直复制至数组结尾(默认为 arr.length)。