Array 操作篇
一. Array 操作篇
本文将介绍 JavaScript 里 Array 的相关操作,内容包括:
构造器:
Array()
静态方法
Array.from()
,Array.of()
Array.isArray()
实例属性
Array.prototype.length
实例方法
1. 构造器
constructor, 构造器/构造函数
Array()
构造器用于创建 Array 对象。
let nums1 = [1, 2, 3, 4]; // 数组字面量
let nums2 = new Array(1, 2, 3, 4); // 用数组元素初始化
let nums3 = new Array(4); // 用数组长度初始化, [0, 2^32 - 1]
console.log(nums1.length, nums1[0], nums1[3]); // 4 1 4
console.log(nums2.length, nums2[0], nums2[3]); // 4 1 4
console.log(nums3.length, nums3[0], nums3[3]); // 4 undefined undefined
// 字符串类型
let fruits1 = ['apple', 'banana', 'strawberry'];
let fruits2 = new Array('apple', 'banana', 'strawberry');
console.log(fruits1.length, fruits2.length); // 3 3
2. 静态方法
Array.from()
创建一个新的 Array 实例(浅拷贝),从类数组对象或可迭代对象Array.of()
创建一个新的 Array 实例,从参数列表-数组元素Array.isArray()
判断是否为数组,返回布尔值用它来判断 TypedArray 实例,会返回 false
Array.from()
Array.from()
Array.from()
方法从类数组对象或可迭代对象创建一个新的 Array 实例。它有三个参数:
第一个参数:类数组对象/可迭代对象
类数组对象:有
length
属性和索引元素的对象可迭代对象:实现了
@@iterator
方法的对象。内置的可迭代对象有String
,Array
,TypedArray
,Map
,Set
第二个参数:在数组的每个元素上调用的映射函数(可选)
第三个参数:当执行映射函数时的
this
值(可选)
Array.from(obj, mapFn, thisArg)
和 Array.from(obj).map(mapFn, thisArg)
的结果是一样的,只是前者不创建中间数组,且映射函数只接收两个参数 (element, index)
。
“不创建中间数组”对于某类数组尤其重要,比如类型数组,因为中间数组的值必然会被截断以适应合适的类型。
//========= Array-like Objects
Array.from({ length: 5 }, (item, index) => index); // [0, 1, 2, 3, 4]
(function () { return Array.from(arguments) })(11, 22, 33); // [11, 22, 33]
// nodelist
const images = document.getElementsByTagName('img');
const sources = Array.from(images, image => image.src);
const insecureSources = sources.filter(link => link.startsWith('http://'));
//========= Iterable Objects
// Array
Array.from([1, 2, 3]); // [1, 2, 3]
Array.from([1, 2, 3], x => x + x); // [2, 4, 6]
// String
Array.from('hello'); // ['h', 'e', 'l', 'l', 'o']
// Set
const fruits = new Set(['apple', 'banana', 'strawberry', 'apple']);
fruits; // {'apple', 'banana', 'strawberry'}
Array.from(fruits); // ['apple', 'banana', 'strawberry']
// Map
const person = new Map([['name', 'Jane'], ['age', 18], ['sex', 'female']]);
Array.from(person); // [['name', 'Jane'], ['age', 18], ['sex', 'female']]
Array.from(person.keys()); // ['name', 'age', 'sex']
Array.from(person.values()); // ['Jane', 18, 'female']
Array.of()
Array.of()
Array.of()
方法从可变数量的参数列表创建一个新的 Array 实例,不限参数的数量和类型。
Array.of()
和 Array()
构造器之间的区别在于对一个整数参数的处理,比如 Array.of(3)
会创建一个只有一个元素 3 的数组,而 Array(3)
会创建一个 length
属性是 3 的空数组(这意味着一个包含 3 个空槽(slots)的数组,而不是具有实际 undefined
值的槽)。
// 不同点:单个整数时
Array.of(3); // [3]
new Array(3); // [empty × 3], array of 3 empty slots
// 多个时表现一致
new Array(1, 2, 3); // [1, 2, 3]
Array.of(1, 2, 3); // [1, 2, 3]
3. 实例属性
Array 对象的 length
属性设置或返回该数组中元素的数量,它是一个无符号的 32 位整数。
new Array(2 ** 32); // Uncaught RangeError: Invalid array length
new Array(2 ** 32 - 1); // OK
我们可以随时设置 length
属性以对数组进行扩容或缩容。
const nums = [1, 2, 3];
console.log(nums); // [1, 2, 3]
// 扩容
nums.length = 10;
console.log(nums); // [1, 2, 3, empty × 7], empty slots
// 缩容
nums.length = 1;
console.log(nums); // [1]
Array.prototype.length
的属性描述符是:
value
Writable
true ✔️ ️
Enumerable
false
Configurable
false
4. 实例方法
数组的实例方法 Array.prototype.xxx()
比较多,大约 34 个。这里对它们进行下分类,以便更好地理解和记忆。
可变函数
mutation operations, 变异/可变操作, 即会改变原数组的
fill()
值填充
push()
pop()
push_back 在尾部添加一个/多个元素,返回新 length pop_back 删除最后一个元素,返回该元素
unshift()
shift()
push_front 在头部添加一个/多个元素,返回新 length pop_front 删除第一个元素,返回该元素
sort()
reverse()
原地排序 原地反转数组元素
splice()
增/删/改
完整参数(包括可选参数):
fill(value, start, end)
push(element0, element1, ..., elementN)
unshift(element0, element1, ..., elementN)
sort((a,b) => {})
默认是升序,按字符串排
将元素转换为字符串,然后比较它们的 UTF-16 code units 序列
splice(start, deleteCount, item1, item2, itemN)
会更改数组的内容
可以删除或替换现有元素、可以添加新元素(增删改)
eg1. splice()
const nums = [1, 2, 3, 4];
// 删除
nums.splice(2, 1);
console.log(nums); // [1, 2, 4]
// 替换
nums.splice(2, 1, 44);
console.log(nums); // [1, 2, 44]
// 新添加
nums.splice(2, 0, 66, 666, 6666, 66666);
console.log(nums); // [1, 2, 66, 666, 6666, 66666, 44]
// 操作多个
nums.splice(3);
console.log(nums); // [1, 2, 66]
eg2. sort()
// 默认按字符串排序
let names = ['Jobs', 'Bob', 'Ann', 'Charl', 'David'];
names.sort(); // ['Ann', 'Bob', 'Charl', 'David', 'Jobs']
// 数字也会按字符串排(不符合预期)
let nums = [22, 0, -20, 7, -11, -9, 0, 1];
nums.sort(); // [-11, -20, -9, 0, 0, 1, 22, 7]
// 按数字排
nums.sort((a, b) => a > b ? 1 : -1); // -20, -11, -9, 0, 0, 1, 7, 22
索引/查找
at()
传下标索引,支持负数
includes()
传元素,返回 boolean
indexOf()
lastIndexOf()
传元素,返回第一个(最小)下标索引 传元素,返回倒数第一个(最大)下标索引
find()
findIndex()
传函数,返回满足条件的第一个元素 传函数,返回满足条件的第一个下标索引
完整参数(包括可选的):
传元素:检查每个元素是否和值相等
includes(searchElement, fromIndex)
indexOf(searchElement, fromIndex)
lastIndexOf(searchElement, fromIndex)
传函数:使用测试函数判断
箭头函数
find((element, index, array) => { ... })
回调函数
find(callbackFn, thisArg)
内联函数
find(function(element, index, array) { ... }, thisArg)
let nums = [1, 2, 4, 8, 16, 32];
nums.at(-1); // 32
nums[nums.length - 1]; // 32
nums.find(x => x > 5); // 8
nums.findIndex(x => x > 5); // 3
nums.find((x, i, arr) => { console.log(x, i, arr); return x > 5; }); // 8
// 1 0 [1, 2, 4, 8, 16, 32]
// 2 1 [1, 2, 4, 8, 16, 32]
// 4 2 [1, 2, 4, 8, 16, 32]
// 8 3 [1, 2, 4, 8, 16, 32]
判定
some()
传测试函数,若至少有一个元素满足,则返回 true
every()
传测试函数,若每个元素都满足,则返回 true
let nums = [1, 2, 4, 8, 16, 32];
nums.some(x => x > 5); // true
nums.every(x => x % 2 === 0); // false
新数组
entries()
key/value pairs 二维数组
keys()
values 一维数组
values()
keys 一维数组
新的数组迭代器
map()
传函数,对数组的每个元素用回调,用返回值组成一个新数组
filter()
传函数,用过滤函数返回 true 的元素们组成一个新数组
slice()
传下标,截取数组(返回浅拷贝) 参数 (start, end) 对应下标范围 [start, end)
concat()
合并两个/多个数组 参数 (value0, value1, ... , valueN)
flat()
flatMap()
let nums = [1, 2, 4, 8, 16, 32];
nums.map(x => x > 5); // [false, false, false, false, false, true, true]
nums.map(x => x + x); // [2, 4, 6, 8, 10, 12, 14]
nums.filter(x => x > 5); // [8, 16, 32]
其它
迭代
forEach()
传函数,为每个数组元素执行一次提供的函数
字符串
join()
将数组变成字符串,默认用字符","
toString()
toLocaleString()
字符串 localized 字符串
其它
groupBy()
groupByToMap()
传函数,根据返回值将元素分组到一个对象里 传函数,根据返回值将元素分组到 Map 里
reduce()
reduceRight()
传 reducer 函数,从左到右 传 reducer 函数,从右到左
copyWithin()
复制一系列数组元素
总结
本文简要介绍了 JavaScript 里 Array 的基本操作,旨在对其有个整体了解和感性认识。
构造器
Array()
创建 Array 对象
静态方法
Array.from()
Array.of()
创建一个新的 Array 实例
Array.isArray()
实例属性
Array.prototype.length
可变长数组
实例方法
fill()
push()
, pop()
可模拟栈
unshift()
, shift()
可模拟队列
sort()
, reverse()
原地
splice()
增删改
可变操作
at()
includes()
indexOf()
, lastIndexOf()
find()
, findIndex()
索引/查找
some()
every()
判定
entries()
keys()
values()
返回新数组
map()
, filter()
slice()
, concat()
flat()
, flatMap()
返回新的数组迭代器
forEach()
迭代
join()
toString()
toLocaleString()
字符串
groupBy()
, groupByToMap()
reduce()
, reduceRight()
copyWithin()
其它
各个方法的更多详情,可查阅其接口文档。
主要参考
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
Last updated