JavaScript基础:数组

204 阅读7分钟

Array类型

JavaScript中数组是有序数据的集合,但其每一项可以是任意类型但数据,且可以动态调整数组的大小,即可以随着数据的添加自动增长以容纳新增数据。数组的length属性不仅可读而且是可以修改的,也就是说可以通过设置数组length属性,可以从数组的末尾移除项或向数组中添加新项。

const arr = [];
arr[1] = 2;
arr.length = 5;
arr[4] = 'test';

创建数组

创建数组的方法基本上可以分为三种:一种是使用Array构造函数;二种是使用数组字面量;三种是通过扩展运算符和转换函数即...Array.from()Array.of()

// 构造函数创建数组时,当只传递一个值创建数组时,如果传递的是数值,则会按照该数值创建包含给定项数的数组;而如果传递的是其他类型的参数,则会创建包含那个值 的只有一项的数组
const arr1 = new Array(30); // 创建length值为30的数组
const arr2 = new Array('test'); // 创建包含一个test字符串的数组
// 使用对象字面量
const arr3 = ["red", "blue", "green"];
const arr4 = [];

// 使用扩展运算符
const arr1 = [...[1, 2, 3]]; // arr1 = [1, 2, 3];
const [arr2, ...arr3] = [1, 2, 3]; // arr2 = 1 arr3 = [2, 3]
const arr4 = [...'hello']; // arr4 = ['h', 'e', 'l', 'l', 'o']

// 使用Array.from将类数组对象和可迭代对象转为数组
const arr1 = Array.from({1: 'a', 2: 'b', length: 2}); // arr1 = ['a', 'b']
const arr2 = Array.from(new Set([1, 2, 3]), val => val + 2); // arr2 = [3, 4, 5]

// 使用Array.of将一组值转为数组
const arr1 = Array.of(1, 2, 3); // arr1 = [1, 2, 3]避免了使用Array构造函数时参数个数的不同,会导致Array()的行为有差异

检测数组

确定某个对象是不是数组可以采取三种方法:一种使用instanceof;二种使用Array.isArray;三种使用Object.prototype.toString.call/Object.prototype.toString.apply

// 使用instanceof
const arr = [];
const isArr = arr instanceof Array; // true
// 使用Array.isArray
const arr = [];
const isArr = Array.isArray(arr); // true
// 使用Object.prototype.toString.call
const arr = [];
const isArr = Object.prototype.toString.call(arr); // "[object Array]"

转换方法

所有对象都具有toLocaleString()toString()valueOf()方法,对数组调用toString()toLocaleString()返回由数组中每个值的字符串形式拼接而成的一个以逗号分隔的字符串,该字符串是调用数组每一项的toString()toLocaleString()方法。调用valueOf()返回的还是数组。数组还有join方法进行转换,传入一个参数作为分隔符。

const person = {
  name: 'test',
  toString () {
    return 'person string';
  },
  toLocaleString () {
    return 'person local string';
  },
}
const arr1 = ['arr', person];
arr1.valueOf(); // ['arr', person]
arr1.toString(); // 'arr', 'person string'
arr1.toLocaleString(); // 'arr', 'person local string'
arr1.join('-'); // test-person string

数组栈方法

数组提供的实现栈行为的方法pushpoppush()方法可以接收任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度。而pop()方法则从数组末尾移除最后一项,减少数组的 length 值,然后返回移除的项。

const arr1 = [1, 2];
arr1.push(3, 4); // 4
arr1.pop(); // 4

数组队列方法

数组提供的实现模拟队列后进先出行为的方法shiftpush。这里我们介绍shiftunshift方法,unshitshiftpushpop方法类似,只不过它们操作的数组的头部。

const arr1 = [1, 2];
arr1.unshift(3, 4); // length: 4; arr1: 3, 4, 1, 2
arr1.shift(); // 0

数组重排序方法

实现数组重排序的方法主要包括两个reversesortreverse()方法会反转数组项的顺序。sort()方法在默认情况下会调用每个数组项的toString()转型方法,然后比较得到的字符串,以确定如何排序。也可以传入比较函数,比较函数接收两个参数,如果第一个参数应该位于第二个之前则返回一个负数,如果两个参数相等 则返回 0,如果第一个参数应该位于第二个之后则返回一个正数。

const arr1 = [1, 0, 2];
arr1.reverse(); // [2, 0, 1]
arr1.sort((a, b) => a - b); // [0, 1, 2]

数组操作方法

javascript为操作已经包含在数组中的项提供了许多方法。concat()方法可以基于当前数组拼接创建一个新数组。 slice()方法可以基于当前数组从起始位置到结束位置(不包括结束位置的项)创建一个新数组。 splice()基于当前数组对齐进行删除、插入、修改,返回从原始数组中删除的项(如果没有删除任何 项,则返回一个空数组),会改变原数组的值。

const arr1 = [1, 2];
const arr2 = arr1.concat(3, [4, 5]); // [1, 2, 3, 4, 5]
arr2.slice(1, 3); // [2, 3]
arr2.splice(0, 1); // 删除操作, 返回[1]
arr2.splice(0, 0, 6, 7); // 插入操作, 返回[]
arr2.splice(0, 1, 7); // 替换操作, 返回[6]

copyWithin()方法,在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。

Array.prototype.copyWithin(target, start = 0, end = this.length)
/* 
- target(必需):从该位置开始替换数据。如果为负值,表示倒数。
- start(可选):从该位置开始读取数据,默认为 0。如果为负值,表示从末尾开始计算。
- end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示从末尾开始计算。
*/
const arr1 = [1, 2, 3, 4, 5];
arr1.copyWithin(0, 3); // [4, 5, 3, 4, 5]

fill方法使用给定值,填充一个数组。

Array.prototype.fill(target, start = 0, end = this.length)
/* 
- target(必需):填充的值。
- start(可选):从该位置开始填充数据,默认为 0。如果为负值,表示从末尾开始计算。
- end(可选):到该位置前停止填充数据,默认等于数组长度。如果为负值,表示从末尾开始计算。
*/
const arr1 = [1, 2, 3, 4, 5];
arr1.fill(0, 1, 3); // [1, 0, 0, 4, 5]

数组位置方法

indexOf()lastIndexOf():这两个方法都接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中,indexOf()方法从数组的开头(位置 0)开始向后查找,lastIndexOf()方法则从数组的末尾开始向前查找。这两个方法都返回要查找的项在数组中的位置,或者在没找到的情况下返回-1。

const arr1 = [1, 2, 3, 4, 5]
arr1.indexOf(1); // 0
arr1.lastIndexOf(3, 1); // -1

find()findIndex()通过对所有数组成员依次执行该回调函数,用于找出第一个符合条件的数组成员和数组成员的位置。

const arr1 = [1, 2, 3, 4, 5];
arr1.find((val, index, arr) => val > 6); // undefined
arr1.find((val, index, arr) => val > 4); // 4
arr1.findIndex((val, index, arr) => val > 6); // -1
arr1.find((val, index, arr) => val > 4); // 3

includes方法进行数组查找是仅返回一个布尔值,表示某个数组是否包含给定的值。

Array.prototype.includes(val[, start]);
/*
- val[必需]:需要查找的值;
- start[可选]:查找的起始位置,默认为 0。如果为负值,表示从末尾开始计算。
*/
const arr1 = [1, 2, 3];
arr1.includes(1); // true
arr1.includes(1, 2); // false

数组遍历方法

数组遍历的方法主要包括entries()keys()values()for...of

const arr1 = [1, 2, 3];
for (const val of arr1) {
  console.log(val); // 1, 2, 3
}
for (const index of arr1.keys()) {
  console.log(index); // 0, 1, 2
}
for (const val of arr1.values()) {
  console.log(val); // 1, 2, 3
}
for (const [index, val] of arr1.entries()) {
  console.log([index, val]); // [0, 1], [1, 2], [2, 3]
}

数组迭代方法

这些方法中的函数会接收三个参数:数 组项的值、该项在数组中的位置和数组对象本身。

  • every():对数组中的每一项运行给定函数,如果该函数对每一项都返回 true,则返回 true。  filter():对数组中的每一项运行给定函数,返回该函数会返回 true 的项组成的数组。
  • forEach():对数组中的每一项运行给定函数。这个方法没有返回值。
  • map():对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。
  • some():对数组中的每一项运行给定函数,如果该函数对任一项返回 true,则返回 true。
const arr1 = [1, 2, 3];
arr1.every(val => val > 0); // true
arr1.some(val => val > 4); // false
arr1.filter(val => val >= 2); // [1, 2]
arr1.map(val => val + 1); // [2, 3, 4]
arr1.forEach(val => console.log(val)); // 1, 2, 3

数组归并方法

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

const arr1 = [1, 2, 3]
const sum = 0;
const start = 4;
arr1.reduce((pre, cur, index, arr) => {return pre + cur}, start); // 10

数组拉平方法

flat()flatMap()可以对嵌套的数组进行拉平操作。

Array.prototype.flat([level])
/*
- level[可选]:拉平的层级,默认拉平一层
*/
Array.prototype.flatMap((cur, index, arr) => {}[, thisArg])
/*
对嵌套数组拉平一层进行map操作
*/
const arr1 = [1, [2, [3, 4]]];
const arr2 = arr1.flat(); // [1, 2, [3, 4]]
arr2.map(val => val + 1); // [2, 3, 4, 5]