Open anjia opened 2 years ago
本文将介绍 JavaScript 里 Array 的相关操作,内容包括:
Array()
Array.from()
, Array.of()
Array.isArray()
Array.prototype.length
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
Array.from()
创建一个新的 Array 实例(浅拷贝),从类数组对象或可迭代对象Array.of()
创建一个新的 Array 实例,从参数列表-数组元素Array.isArray()
判断是否为数组,返回布尔值
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 实例,不限参数的数量和类型。
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]
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 |
数组的实例方法 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) => {})
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() |
其它 |
各个方法的更多详情,可查阅其接口文档。
目录