前端小菜,先别慌——JS篇(数组)

513 阅读9分钟

数组(Array)

随着前端MVVM框架(React,Vue,Angular)的全面普及,前端工程师在数据操作上耗费的时间越来越多;数组作为数据的主要载体,自然挑起了大梁,在前端编码中扮演者不可或缺的角色。因此,数组是菜鸟们的前端成长之路上,必须消灭的一个精英怪。

本文属于基础知识归纳整理类文章,如果你了解数组的基本用法,但是对数组使用没有一个清晰全面的认知,那本文应该适合你。

本文主要讲解数组是如何创建的,数组有哪些遍历方法,数组的实例方法中哪些是会改变数组自身的;最后,我从返回值的角度,分析了不同数组方法的使用场景。

1. 开始之前

在讲数据的创建,访问,遍历以及其他具体的操作方法之前,我觉得有必要先跟大家讲一下数组的基本概念。比如数组对象,数组对象的属性,数组对象的方法,数组实例,数组实例的属性以及数组实例的方法。

  • 数组对象—— Array是常用的标准内置对象,类似的还有String,Date,Math,Object等
  • 数组对象的方法——主要有Array.from(),Array.of(),Array.isArray()
  • 数组实例——通过new Array等方式创建的具体实例
  • 数组实例的属性——主要有length,以及prototype
  • 数组实例的方法——继承自Array.prototype的方法

注意:数组对象的方法与数组实例的方法是两个不同的概念,使用方式也有所不同。如下所示,数组对象的方法使用,是Array后面跟方法名称,而数组实例的方法,则是具体的数组后面跟方法名称。

// 数组对象的方法
var arr=Array.from(["华为","OPPO","VIVO"]);

// 数组实例的方法
["华为","OPPO","VIVO"].pop();

2. 数组创建

数组实例的创建,通常使用以下几种方式。

// 方式一 字面量创建
var arr=["华为","OPPO","VIVO"];

// 方式二 构造函数创建
var arr=new Array();
arr[0]="华为";
arr[1]="OPPO";
arr[2]="VIVO";

// 上述方式也可以直接传参初始化
var arr=new Array("华为","OPPO","VIVO");

// 也可以,先指定长度
var arr=new Array(3);

// 当然,ES6出来之后,我们又多了全新的两种方式:
// 将参数中所有值作为元素形成数组。
var arr=Array.of("华为","OPPO","VIVO");

//将数组,类数组对象或可迭代对象转化为数组
var arr=Array.from(["华为","OPPO","VIVO"]);

3. 数组操作——遍历元素

方法名称 方法描述
forEach() 为数组中的每个元素执行一次回调函数。
entries() 返回一个数组迭代器对象,该迭代器会包含所有数组元素的键值对。
keys() 返回一个数组迭代器对象,该迭代器会包含所有数组元素的键。
values() 返回一个数组迭代器对象,该迭代器会包含所有数组元素的值。
every() 如果数组中的每个元素都满足测试函数,则返回 true,否则返回 false。
some() 如果数组中至少有一个元素满足测试函数,则返回 true,否则返回 false。
filter() 将所有在过滤函数中返回 true 的数组元素放进一个新数组中并返回。
find() 找到第一个满足测试函数的元素并返回那个元素的值,如果找不到,则返回 undefined。
findIndex() 找到第一个满足测试函数的元素并返回那个元素的索引,如果找不到,则返回 -1。
map() 返回一个由回调函数的返回值组成的新数组。
reduce() 从左到右执行,并把上次回调函数的返回值放在一个暂存器中传给下次回调函数,并返回最后一次回调的返回值。
reduceRight() 从右到左执行,并把上次回调函数的返回值放在一个暂存器中传给下次回调函数,并返回最后一次回调的返回值。

4. 数组操作——改变自身

方法名称 方法描述
push() 在数组的末尾增加一个或多个元素,并返回数组的新长度。
pop() 删除数组的最后一个元素,并返回这个元素。
unshift() 在数组的开头增加一个或多个元素,并返回数组的新长度。
shift() 删除数组的第一个元素,并返回这个元素。
reverse() 颠倒数组中元素的排列顺序,即原先的第一个变为最后一个,原先的最后一个变为第一个。
sort() 对数组元素进行排序,并返回当前数组。
splice() 在任意的位置给数组添加或删除任意个元素。
fill() 将数组中指定区间的所有元素的值,都替换成某个固定的值。
copyWithin() 在数组内部,将一段元素序列拷贝到另一段元素序列上,覆盖原有的值。

5. 数组操作——不改变自身

方法名称 方法描述
concat() 返回一个由当前数组和其它若干个数组或者若干个非数组值组合而成的新数组。
includes() 判断当前数组是否包含某指定的值,如果是返回 true,否则返回 false。
join() 连接所有数组元素组成一个字符串。
slice() 抽取当前数组中的一段元素组合成一个新数组。
toSource() 返回一个表示当前数组字面量的字符串。遮蔽了原型链上的 Object.prototype.toSource() 方法。
toString() 返回一个由所有数组元素组合而成的字符串。遮蔽了原型链上的 Object.prototype.toString() 方法。
toLocaleString() 返回一个由所有数组元素组合而成的本地化后的字符串。遮蔽了原型链上的 .toLocaleString() 方法。
indexOf() 返回数组中第一个与指定值相等的元素的索引,如果找不到这样的元素,则返回 -1。
lastIndexOf() 返回数组中最后一个(从右边数第一个)与指定值相等的元素的索引,如果找不到这样的元素,则返回 -1。

6. 数组操作代码演示

单纯的看文档描述,没有一定经验的人,估计很难理解它们的具体使用场景;对于我们菜鸟而言,操练代码真刀实弹的干才是王道;为了方便大家的理解,我特将数组操作的方法,按照返回结果分类整理,以便大家理解,下面是各个方法的基本实现:

情形一 返回连接后的新数组
  • concat()
var arrOdd = [7, 3, 5, 1, 11, 9];
var arrEven = [6, 8, 2, 4, 10];
var arrNew = arrOdd.concat(arrEven);
console.log("concat", arrNew);
// 输出 [7, 3, 5, 1, 11, 9, 6, 8, 2, 4, 10]
情形二 返回与原数组长度一致的对象(新数组/当前数组/数组迭代器对象)
  • map()
  • reverse()
  • sort()
  • entries()
  • keys()
  • value()
var arrOdd = [7, 3, 5, 1, 11, 9];
var arrNew = arrOdd.map(item => item * 2);
console.log("map", arrNew);
// 输出[14, 6, 10, 2, 22, 18]
// 长度以及顺序与原数组一致,数组元素的值发生变化(也可以不变,即返回原始值)

arrNew = arrOdd.reverse();
console.log("reverse", arrNew);
// 输出[9, 11, 1, 5, 3, 7]
// 长度以与原数组一致,顺序反转,数组元素的值不变

arrNew = arrOdd.sort((a, b) => {
  if (a > b) return 1;
  if (a < b) return -1;
  return 0;
});
console.log("sort", arrNew);
// 输出[1, 3, 5, 7, 9, 11]
// 长度以与原数组一致,顺序按照指定的排列,数组元素的值不变

// 上面语句可以简写为: 
arrNew = arrOdd.sort((a, b) => a - b);

var iterator = arrOdd.entries();
for(let item of iterator){
  console.log(item);
}
// 输出[0,1],[1,3],[2,4],[3,7],[4,9],[5,11]
// 返回数组迭代器对象,包含键值对

iterator = arrOdd.keys();
for(let item of iterator){
  console.log(item);
}
// 输出1, 2, 3, 4, 5
// 返回数组迭代器对象,仅包含键

iterator = arrOdd.values();
for(let item of iterator){
  console.log(item);
}
// 输出1, 3, 5, 7, 9, 11
// 返回数组迭代器对象,仅包含元素值
情形三 返回被移除或者提取的数组元素
  • pop()
  • shift()
  • slice()
  • splice()
  • filter()
// pop(),shift(),slice(start_index, upto_index)
var arrOdd = [1, 3, 5, 7, 9, 11, 13];
var arrReturn = arrOdd.pop();
console.log(arrReturn);
// 输出 13
// 返回尾部移除的数组元素

arrReturn = arrOdd.shift();
console.log(arrReturn);
// 输出 1
// 返回头部移除的数组元素

arrReturn = arrOdd.slice(2,4);
console.log(arrReturn);
// 输出 [7, 9]  注意,此处不包含11
// 返回开始到结束的数组元素(不包含结束点的元素)

// filter(callback[, thisObject]) 
arrReturn = arrOdd.filter(item=>item> 4);
console.log(arrReturn);
// 输出 [5, 7, 9, 11] 
// 返回符合筛选条件的值
 
情形四 返回数组长度
  • push()
  • unshift()
var arrOdd = [1, 3, 5, 7, 9, 11];
var length = arrOdd.push(13);
console.log(length, arrOdd);
// 输出length : 7 , arrOdd: [1, 3, 5, 7, 9, 11, 13]
// 返回插入成功后的数组元素

var length = arrOdd.unshift(-1);
console.log(length, arrOdd);
// 输出length : 8 , arrOdd: [-1, 1, 3, 5, 7, 9, 11, 13]
// 返回插入成功后的数组元素
情形五 返回匹配的索引
  • findIndex()
  • indexOf()
  • lastIndexOf()
// arr.findIndex(callback[, thisArg])
var arrOdd = [1, 3, 5, 7, 5, 11];
var index = arrOdd.findIndex(item => item > 5);
console.log(index);
// 输出 index : 3
// 返回能匹配自定义函数的第一个元素的索引

// indexOf(searchElement[, fromIndex]) 第二个参数决定开始检索的位置
index = arrOdd.indexOf(5);
console.log(index);
// 输出 index : 2
// 返回首个被找到的元素在数组中的索引位置; 若没有找到则返回 -1

index = arrOdd.lastIndexOf(5);
console.log(index);
// 输出 index : 4
// 返回该元素最后一次出现的索引,如未找到返回-1
情形六返回 true 或者 false
  • every()
  • some()
  • includes()
// every(callback[, thisObject])
var arrOdd = [1, 3, 5, 7, 5, 11];
var result = arrOdd.every(item => item > 5);
console.log(result);
// 输出 index : false
// 判断是否全部元素都大于5

// some(callback[, thisObject]) 
result = arrOdd.some(item => item > 5);
console.log(result);
// 输出 index : true
// 判断是否有元素都大于5

// arr.includes(valueToFind[, fromIndex])
result = arrOdd.includes(5);
console.log(result);
// 输出 index : true
// 判断是否有元素的值为5

情形七 返回计算出的单一值
  • reduce()
  • reduceRight()
// reduce(callback[, initialValue]) 
// 注意initialValue的使用,根据准备返回的类型,灵活的为他赋值为0 ,{}, [] 

// 累加计算
var arrOdd = [1, 3, 5, 7, 5, 11];
var result = arrOdd.reduce((acc, item) => {
  return acc + item;
}, 0);
console.log(result);
// 输出 result : 32

var result = arrOdd.reduce((acc, item) => {
  acc.push(item + 1);
  return acc;
}, []);
console.log(result);
// 输出 result : [2, 4, 6, 8, 6, 12]

var arr = [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4];
var result = arr.reduce((acc, item) => {
  if (acc.indexOf(item) < 0) {
	acc.push(item);
  }
  return acc;
}, []);
// 输出 result : [2, 4, 6, 8, 6, 12]

// reduceRight与reduce使用基本一致,只是操作顺序与其相反(从右到左),所以不在赘述。

总结

数组操作是JavaScript中的基础知识,如果能够灵活运用,往往能极大地帮助自己提升开发效率。作为一个有追求的前端小菜,务必要详细了解数组每一个方法的使用,这样才能够在实际运用中信手拈来。最后,强烈推荐大家去MDN进行学习,学习链接: developer.mozilla.org/zh-CN/docs/…

希望这文章能对大家有所帮助,如果觉得还行,请大家给一个鼓励的赞吧! 如果觉得哪儿有问题的,也欢迎批评指正,谢谢!