这是我参与更文挑战的第四天,活动详情查看:更文挑战
数组是 JavaScript 工作中最常用的数据类型之一,今天总结下各种场景下的数组方法,话不多说。show you the code
JavaScript 中的数组是什么
数组是一串连续的内存位置,用来保存某些值。注意重点,“连续”(continuous,或 contiguous),这很重要。
Array 的底层硬件实现由一个叫做内存管理器
的东西,每当申请数组的时候--计算机实际上是在内存中开辟了一段连续的地址,每一个地址就可以直接通过内存管理器
上图中示例的就是数组相应的内存地址,如果访问数组中第一个元素或者数组最后一个元素--即访问数组中任意一个元素, 时间复杂度都为常数复杂度 O(1)
因为数组可以随机访问任何一个元素,所以它的访问时间还是比较快的,这是它的特征之一
创建数组
Array 构造函数
// 初始化空数组
const arr2 = new Array();
//初始化长度为7的数组
const arr3 = new Array(7);
// 创建包含N个元素的数组
const arr4 = new Array("red", "blue", "green");
// 通过fill填充元素
const arr5 = new Array(7).fill(1);
使用 fill()
填充元素的问题
const arr = new Array(7).fill({ a: 1 });
const arr = new Array(7).fill({ a: 1 });
console.log("---arr---beforeUpdate");
console.log(arr);
arr[4].a = 6;
console.log("---arr---");
console.log(arr);
打印出修改之前的
arr
及修改之后的 `arr``
通过 fill
填充的数组元素,并且元素是引用类型时, 修改某一个元素会影响到其他的元素
字面量表示法
// 创建空数组
const arr = [];
// 创建包含N个元素的数组
const arr1 = [1, 2, 3, 4];
数组空位
使用数组字面量初始化数组时,可以使用一串逗号来创建空位(hole),ES6 标准明确将空位转为undefined
const options = [1, , , , 5];
for (const option of options) {
console.log(option === undefined);
}
// false
// true
// true
// true
// false
Array.from()
作用:将类数组转化为数组实例
"类数组"对象本质是任何可迭代的结构,或者有一个length
属性和可索引元素的结构。原生具备 Iterator
接口的数据结构有:
Array
Map
Set
String
TypedArray- 函数的
arguments
对象 NodeList
对象
// 字符串会被拆分为单字符数组
console.log(Array.from("Matt")); // ["M", "a", "t", "t"]
// 可以使用from()将集合和映射转换为一个新数组 const m = new Map().set(1, 2)
const m = new Map().set(1, 2).set(3, 4);
const s = new Set().add(1).add(2).add(3).add(4);
console.log(Array.from(m)); // [[1, 2], [3, 4]]
console.log(Array.from(s)); // [1, 2, 3, 4]
Array.of()
// 把一组参数转化为数组
console.log(Array.of(1, 2, 3, 4)); // [1, 2, 3, 4]
console.log(Array.of(undefined)); // [undefined]
判断是否是数组类型
instanceof
constructor
Object.prototype.isPrototypeOf
getPrototypeOf
Object.prototype.toString
Array.isArray
let arr = [];
// 1. instanceof
arr instanceof Array;
// 2. constructor
arr.constructor === Array;
// 3. Object.prototype.isPrototypeOf
Array.prototype.isPrototypeOf(arr);
// 4. getPrototypeOf
Object.getPrototypeOf(arr) === Array.prototype;
// 5. Object.prototype.toString
Object.prototype.toString.call(arr) === "[object Array]";
// 6. Array.isArray ES6 新增- 推荐
Array.isArray(arr);
查找指定的数组元素
indexOf
: 返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1lastIndexOf
: 返回指定元素(也即有效的 JavaScript 值或变量)在数组中的最后一个的索引,如果不存在则返回 -1。从数组的后面向前查找includes
: 用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回 false。find
: 返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefinedfindIndex
: 返回数组中满足提供的测试函数的第一个元素的索引。若没有找到对应元素则返回-1filter
: 返回一个新数组, 其包含通过所提供函数实现的测试的所有元素
下面是一个查找数组中某个元素是否存在的例子,
const list = ["小王", "小李", "小杨", "小胡", "小高", "小赵", "小钱", "小孙"];
// 7
const res1 = list.indexOf("小孙");
// 7
const res2 = list.lastIndexOf("小孙");
// 小孙
const res3 = list.find((item) => item === "小孙");
// 7
const res4 = list.findIndex((item) => item === "小孙");
// ['小孙']
const res5 = list.filter((item) => item === "小孙");
// true
const res6 = list.some((item) => item === "小孙");
// true
const res7 = list.includes("小孙");
改变原有数组的方法
添加元素
push
: 将一个或多个元素添加到数组的末尾,并返回该数组的新长度
添加一个对象到尾部的位置, 使用 Array.push
.
let car = {
color: "red",
type: "cabrio",
registration: new Date("2016-05-02"),
capacity: 2,
};
cars.push(car);
unshit
: 将一个或多个元素添加到数组的开头,并返回该数组的新长度(该方法修改原有数组)
在头部添加一个对象, 使用 Array.unshift
.
let car = {
color: "red",
type: "cabrio",
registration: new Date("2016-05-02"),
capacity: 2,
};
cars.unshift(car);
concat
: 合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组
const array1 = ["a", "b", "c"];
const array2 = ["d", "e", "f"];
const array3 = array1.concat(array2);
console.log(array3);
// expected output: Array ["a", "b", "c", "d", "e", "f"]
删除元素
pop
: 从数组中删除最后一个元素,并返回该元素的值。此方法更改数组的长度
const plants = ["broccoli", "cauliflower", "cabbage", "kale", "tomato"];
console.log(plants.pop());
// expected output: "tomato"
shift
:从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。
const array1 = [1, 2, 3];
const firstElement = array1.shift();
console.log(array1);
// expected output: Array [2, 3]
console.log(firstElement);
// expected output: 1
从数组中间 添加/删除元素
splice(a,b,c)
: 通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。- a:要截去的开始位置
- b:截去的长度
- c:要添加的元素
添加一个对象到中间位置, 使用 Array.splice
. 此方法非常方便,因为它也可以删除数组的某一个元素。 注意其参数:
Array.splice(
{index where to start},
{how many items to remove},
{items to add}
);
因此,如果我们要在第五个位置添加红色敞篷车,可以像下面一样使用:
let car = {
color: "red",
type: "cabrio",
registration: new Date("2016-05-02"),
capacity: 2,
};
cars.splice(4, 0, car);
迭代器方法
什么是数组的迭代器方法
对数组的每一个元素应用一个函数,可以返回一个值,一组值,一个新数组
不生成新数组的迭代器方法
forEach
: 对数组的每个元素执行一次给定的函数
const array1 = ["a", "b", "c"];
array1.forEach((element) => console.log(element));
// expected output: "a"
// expected output: "b"
// expected output: "c"
every
:测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值
const isBelowThreshold = (currentValue) => currentValue < 40;
const array1 = [1, 30, 39, 29, 10, 13];
console.log(array1.every(isBelowThreshold));
// expected output: true
some
:测试数组中是不是至少有 1 个元素通过了被提供的函数测试。它返回的是一个 Boolean 类型
const array = [1, 2, 3, 4, 5];
// checks whether an element is even
const even = (element) => element % 2 === 0;
console.log(array.some(even));
// expected output: true
生成新数组的迭代器方法
slice()
:返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括 end)。原始数组不会被改变。
const animals = ["ant", "bison", "camel", "duck", "elephant"];
console.log(animals.slice(2));
// expected output: Array ["camel", "duck", "elephant"]
console.log(animals.slice(2, 4));
// expected output: Array ["camel", "duck"]
console.log(animals.slice(1, 5));
// expected output: Array ["bison", "camel", "duck", "elephant"]
reduceRight
:接受一个函数作为累加器(accumulator)和数组的每个值(从右到左)将其减少为单个值。
const array1 = [
[0, 1],
[2, 3],
[4, 5],
].reduceRight((accumulator, currentValue) => accumulator.concat(currentValue));
console.log(array1);
// expected output: Array [4, 5, 2, 3, 0, 1]
reduce
:对数组中的每个元素执行一个由您提供的 reducer 函数(升序执行),将其结果汇总为单个返回值。
reducer 函数接收 4 个参数:
- Accumulator (acc) (累计器)
- Current Value (cur) (当前值)
- Current Index (idx) (当前索引)
- Source Array (src) (源数组)
const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
// expected output: 10
// 5 + 1 + 2 + 3 + 4
console.log(array1.reduce(reducer, 5));
// expected output: 15
场景,
-
累加,累乘
-
数组转字符串
-
map
: 创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值
const array1 = [1, 4, 9, 16];
// pass a function to map
const map1 = array1.map((x) => x * 2);
console.log(map1);
// expected output: Array [2, 8, 18, 32]
filter
:创建一个新数组, 其包含通过所提供函数实现的测试的所有元素
const words = [
"spray",
"limit",
"elite",
"exuberant",
"destruction",
"present",
];
const result = words.filter((word) => word.length > 6);
console.log(result);
// expected output: Array ["exuberant", "destruction", "present"]
其他
join()
:将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串。如果数组只有一个项目,那么将返回该项目而不使用分隔符。
const elements = ["Fire", "Air", "Water"];
console.log(elements.join());
// expected output: "Fire,Air,Water"
console.log(elements.join(""));
// expected output: "FireAirWater"
console.log(elements.join("-"));
// expected output: "Fire-Air-Water"
sort()
:对数组的元素进行排序,并返回数组.。默认排序顺序是在将元素转换为字符串,然后比较它们的 UTF-16 代码单元值序.该方法会改变原数组
const months = ["March", "Jan", "Feb", "Dec"];
months.sort();
console.log(months);
// expected output: Array ["Dec", "Feb", "Jan", "March"]
const array1 = [1, 30, 4, 21, 100000];
array1.sort();
console.log(array1);
// expected output: Array [1, 100000, 21, 30, 4]
reverse()
:将数组中元素的位置颠倒,并返回该数组。数组的第一个元素会变成最后一个,数组的最后一个元素变成第一个。该方法会改变原数组。
const array1 = ["one", "two", "three"];
console.log("array1:", array1);
// expected output: "array1:" Array ["one", "two", "three"]
const reversed = array1.reverse();
console.log("reversed:", reversed);
// expected output: "reversed:" Array ["three", "two", "one"]
// Careful: reverse is destructive -- it changes the original array.
console.log("array1:", array1);
// expected output: "array1:" Array ["three", "two", "one"]
实战演练
通过其值在数组中查找特定的对象 - Array.find
如果想在车辆数组中找到一辆红色的. 我们可以使用 Array.find
.
let car = cars.find((car) => car.color === "red");
这个函数返回匹配到的第一个元素:
console.log(car);
// output:
// {
// color: 'red',
// type: 'station wagon',
// registration: 'Sat Mar 03 2018 01:00:00 GMT+0100 (GMT+01:00)',
// capacity: 5
// }
也可以搜索多个值:
let car = cars.find(car => car.color === "red" && car.type === "cabrio");
在这种情况下,我们将获得车辆列表中的最后一辆车.
从数组中获取符合条件的多个元素 - Array.filter
Array.find
方法只返回一个对象. 如果你想获取所有红色的车, 你需要使用 Array.filter
.
let redCars = cars.filter((car) => car.color === "red");
console.log(redCars);
// output:
// [
// {
// color: 'red',
// type: 'station wagon',
// registration: 'Sat Mar 03 2018 01:00:00 GMT+0100 (GMT+01:00)',
// capacity: 5
// },
// {
// color: 'red',
// type: 'cabrio',
// registration: 'Sat Mar 03 2012 01:00:00 GMT+0100 (GMT+01:00)',
// capacity: 2
// }
// ]
转换数组的对象 - Array.map
在数组的所有方法中,Array.map
方法可以说是我们使用最频繁的了:将对象数组转换为不同对象的数组。 这就是 Array.map
的工作。 假设我们要根据汽车的大小将其分为三类
let sizes = cars.map((car) => {
if (car.capacity <= 3) {
return "small";
}
if (car.capacity <= 5) {
return "medium";
}
return "large";
});
console.log(sizes);
// output:
// ['large','medium','medium', ..., 'small']
如果我们需要更多的值,也可以创建一个新的对象:
let carsProperties = cars.map((car) => {
let properties = {
capacity: car.capacity,
size: "large",
};
if (car.capacity <= 5) {
properties["size"] = "medium";
}
if (car.capacity <= 3) {
properties["size"] = "small";
}
return properties;
});
console.log(carsProperties);
// output:
// [
// { capacity: 7, size: 'large' },
// { capacity: 5, size: 'medium' },
// { capacity: 5, size: 'medium' },
// { capacity: 2, size: 'small' },
// ...
// ]
向数组的每个对象添加属性 - Array.forEach
Array.map
会生成新的数组。 那如果我们只想在原来的汽车对象做修改怎么办? 这对Array.forEach
函数是一个很好的使用场景
cars.forEach((car) => {
car["size"] = "large";
if (car.capacity <= 5) {
car["size"] = "medium";
}
if (car.capacity <= 3) {
car["size"] = "small";
}
});
按属性对数组排序 - Array.sort
完成对象转换后,通常需要以一种或另一种方式对它们进行排序。
通常,排序基于每个对象都具有的属性的值。 我们可以使用Array.sort
函数,但是我们需要提供一个定义排序机制的函数(compareFunction)。
译者注:
如果指明了 compareFunction ,那么数组会按照调用该函数的返回值排序。即 a 和 b 是两个将要被比较的元素:
- 如果 compareFunction(a, b) 小于 0 ,那么 a 会被排列到 b 之前;
- 如果 compareFunction(a, b) 等于 0 , a 和 b 的相对位置不变。备注: ECMAScript 标准并不>保证这一行为,而且也不是所有浏览器都会遵守(例如 Mozilla 在 2003 年之前的版本);
- 如果 compareFunction(a, b) 大于 0 , b 会被排列到 a 之前。
- compareFunction(a, b) 必须总是对相同的输入返回相同的比较结果,否则排序的结果将是不确定的。
假设我们要根据汽车的降序对汽车进行排序。
let sortedCars = cars.sort((c1, c2) =>
c1.capacity < c2.capacity ? 1 : c1.capacity > c2.capacity ? -1 : 0,
);
console.log(sortedCars);
// output:
// [
// {
// color: 'purple',
// type: 'minivan',
// registration: 'Wed Feb 01 2017 00:00:00 GMT+0100 (GMT+01:00)',
// capacity: 7
// },
// {
// color: 'red',
// type: 'station wagon',
// registration: 'Sat Mar 03 2018 01:00:00 GMT+0100 (GMT+01:00)',
// capacity: 5
// },
// ...
// ]
如果排序函数的结果为正,则Array.sort
比较两个对象,并将第一个对象放在第二位。 因此,你可以将排序函数视为一个问题:是否将第一个对象放置在第二个位置
确保两个对象的比较值相同时始终将大小比较写为零,以避免不必要的交换.
检查数组中的对象是否满足条件 - Array.every, Array.includes
当我们只需要检查每个对象的特定条件时,即可使用Array.every
和Array.some
。
汽车清单上有红色敞篷车吗? 所有的汽车都能载至少 4 人吗?...
cars.some((car) => car.color === "red" && car.type === "cabrio");
// output: true
您可能还记得函数Array.includes
与Array.some
类似,但只有元素是原始类型时候二者才类似
最后
文章浅陋,欢迎各位看官评论区留下的你的见解!
觉得有收获的同学欢迎点赞,关注一波!