数组是存储有序数据的集合。
// 空数组
const empty = [];
// 带初始值
const numbers = [1, 2, 3, 4, 5];
// 混合类型
const mixed = [1, "东巴文", true, null, { name: "JS" }];
// 多维数组
const matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
// 创建空数组
const arr1 = new Array();
// 指定长度
const arr2 = new Array(5); // [empty × 5]
// 指定元素
const arr3 = new Array(1, 2, 3); // [1, 2, 3]
// 注意:单个数字参数是长度,不是元素
const arr4 = new Array(5); // 长度为5
const arr5 = new Array("5"); // ["5"]
// Array.of:总是创建包含参数的数组
const arr1 = Array.of(5); // [5]
const arr2 = Array.of(1, 2, 3); // [1, 2, 3]
const arr3 = Array.of("东巴文"); // ["东巴文"]
// 从类数组创建
const arr1 = Array.from("东巴文"); // ["东", "巴", "文"]
// 从arguments创建
function foo() {
const args = Array.from(arguments);
}
// 从Set创建
const set = new Set([1, 2, 2, 3]);
const arr2 = Array.from(set); // [1, 2, 3]
// 从Map创建
const map = new Map([[1, "a"], [2, "b"]]);
const arr3 = Array.from(map); // [[1, "a"], [2, "b"]]
// 带映射函数
const arr4 = Array.from([1, 2, 3], x => x * 2); // [2, 4, 6]
每个数组都有length属性。
const arr = [1, 2, 3, 4, 5];
console.log(arr.length); // 5
// length是可写的
arr.length = 3;
console.log(arr); // [1, 2, 3]
arr.length = 0;
console.log(arr); // [](清空数组)
const arr = [1, 2, 3];
arr[10] = 11;
console.log(arr.length); // 11
console.log(arr); // [1, 2, 3, empty × 7, 11]
// 清空数组
const arr = [1, 2, 3];
arr.length = 0;
// 截断数组
const arr2 = [1, 2, 3, 4, 5];
arr2.length = 3; // [1, 2, 3]
// 添加元素
const arr3 = [1, 2];
arr3[arr3.length] = 3; // 相当于push
const arr = ["东", "巴", "文"];
console.log(arr[0]); // "东"
console.log(arr[1]); // "巴"
console.log(arr[2]); // "文"
console.log(arr[3]); // undefined
// 负索引(ES2022)
console.log(arr.at(-1)); // "文"
console.log(arr.at(-2)); // "巴"
const arr = ["东", "巴", "文"];
// 正索引
arr.at(0); // "东"
arr.at(1); // "巴"
// 负索引(从末尾开始)
arr.at(-1); // "文"
arr.at(-2); // "巴"
arr.at(-3); // "东"
arr.at(-4); // undefined
const arr = [1, 2, 3];
arr[0] = 10;
console.log(arr); // [10, 2, 3]
arr[5] = 6;
console.log(arr); // [10, 2, 3, empty × 2, 6]
const arr = ["东", "巴", "文"];
// 传统for循环
for (let i = 0; i < arr.length; i++) {
console.log(i, arr[i]);
}
// 缓存长度(性能优化)
for (let i = 0, len = arr.length; i < len; i++) {
console.log(arr[i]);
}
const arr = ["东", "巴", "文"];
for (const item of arr) {
console.log(item);
}
// 东
// 巴
// 文
// 获取索引
for (const [index, item] of arr.entries()) {
console.log(index, item);
}
const arr = ["东", "巴", "文"];
arr.forEach((item, index, array) => {
console.log(index, item);
});
// 注意:forEach无法中断
// 使用some或every可以模拟中断
arr.some((item, index) => {
if (index === 1) return true; // 中断
console.log(item);
});
const arr = ["东", "巴", "文"];
for (const index in arr) {
console.log(index, arr[index]);
}
// 问题:会遍历自定义属性
arr.custom = "自定义";
for (const index in arr) {
console.log(index); // 0, 1, 2, custom
}
| 方法 | 获取索引 | 可中断 | this | 东巴文建议 |
|---|---|---|---|---|
| for | 是 | 是 | 无 | 性能优先 |
| for...of | 否 | 是 | 无 | 简洁优先 |
| forEach | 是 | 否 | 可指定 | 一般遍历 |
| for...in | 是 | 是 | 无 | 不用于数组 |
稀疏数组是含有空位的数组。
// 构造函数
const arr1 = new Array(5); // [empty × 5]
// 删除元素
const arr2 = [1, 2, 3];
delete arr2[1]; // [1, empty, 3]
// 跳过索引
const arr3 = [1, , 3]; // [1, empty, 3]
arr3[10] = 11; // [1, empty, 3, empty × 6, 11]
const arr = [1, , 3]; // 稀疏数组
const arr2 = [1, undefined, 3]; // 非稀疏数组
console.log(1 in arr); // false(空位)
console.log(1 in arr2); // true(undefined)
// forEach跳过空位
arr.forEach(x => console.log(x)); // 1, 3
// for...of也会跳过
for (const x of arr) {
console.log(x); // 1, 3
}
// map跳过空位
const mapped = arr.map(x => x * 2); // [2, empty, 6]
const arr = new Array(5);
// fill填充
arr.fill(0); // [0, 0, 0, 0, 0]
// from创建
const arr2 = Array.from({ length: 5 }, () => 0);
// 展开运算符
const arr3 = [...new Array(5)].map(() => 0);
类数组对象具有length属性和索引,但不是真正的数组。
// arguments
function foo() {
console.log(arguments); // Arguments对象
console.log(arguments.length);
}
// NodeList
const nodes = document.querySelectorAll("div"); // NodeList
// HTMLCollection
const children = document.body.children; // HTMLCollection
// 字符串
const str = "东巴文"; // 类数组
// Array.from
const arr1 = Array.from(arguments);
// 展开运算符
const arr2 = [...arguments];
// slice
const arr3 = Array.prototype.slice.call(arguments);
// Array.from带映射
const arr4 = Array.from(arguments, x => x * 2);
// Array.isArray(推荐)
Array.isArray([1, 2, 3]); // true
Array.isArray("123"); // false
// instanceof(有跨框架问题)
[1, 2, 3] instanceof Array; // true
// Object.prototype.toString
Object.prototype.toString.call([1, 2, 3]); // "[object Array]"
// 将arguments转为数组
function sum() {
const args = Array.from(arguments);
return args.reduce((a, b) => a + b, 0);
}
// 操作DOM节点列表
const divs = document.querySelectorAll("div");
const divArray = Array.from(divs);
divArray.forEach(div => div.style.color = "red");
// 字符串处理
const chars = Array.from("东巴文");
console.log(chars); // ["东", "巴", "文"]
// 最可靠的方法
Array.isArray([1, 2, 3]); // true
Array.isArray({ length: 3 }); // false
Array.isArray("123"); // false
Array.isArray(null); // false
Array.isArray(undefined); // false
// instanceof
[1, 2, 3] instanceof Array; // true
// 问题:跨iframe时可能失败
// constructor
[1, 2, 3].constructor === Array; // true
// 问题:constructor可以被修改
// Object.prototype.toString(最通用)
function isArray(value) {
return Object.prototype.toString.call(value) === "[object Array]";
}
掌握了数组基础后,让我们继续学习:
东巴文(db-w.cn) - 让编程学习更简单
📦 东巴文寄语:数组是JavaScript中最常用的数据结构,掌握数组的创建、访问、遍历是基础中的基础。理解稀疏数组和类数组对象,能让你更好地处理各种边界情况。在 db-w.cn,我们帮你打好每一个基础!