前端成长路线第 N 章:当你觉得你已经掌握了数组,其实只是你没见过它“进阶形态”的模样。
今天这篇文章,就带你系统梳理数组的使用细节 + 面试必考 + 源码分析 + 实战技巧!
🪜 前言:数组初学者的“自我安慰”
你可能学会了这些:
const arr = [1, 2, 3];
arr.forEach(v => console.log(v));
你可能也听过这些:
arr.map()
arr.filter()
arr.reduce()
但你真的理解:
entries()有多香?for...in和for...of的区别?- 为什么
Array.from()比 new Array() 更安全? - 什么是数组迭代器?
- 如何优雅高效地遍历数组?
如果还没掌握?今天这篇文章一次讲透!
📦 一、数组基础操作回顾
在正式进入“高级数组修仙”前,我们快速复习基础。
const arr = ['🍎', '🍌', '🍒'];
arr.length→ 数组长度arr.push()/arr.pop()→ 尾部增删arr.shift()/arr.unshift()→ 头部增删arr.includes('🍌')→ 是否包含arr.indexOf()/arr.lastIndexOf()→ 查索引arr.slice()/arr.splice()→ 截取 / 修改原数组
⚔️ 二、## for...in vs for...of:傻傻分不清楚?
for...in:遍历“键”(index),适用于对象
for (let key in [10, 20, 30]) {
console.log(key); // 0, 1, 2
}
for...of:遍历“值”,适用于数组/字符串/Set/Map等
for (let val of [10, 20, 30]) {
console.log(val); // 10, 20, 30
}
🚫⚠️ 千万别用 for...in 遍历数组,它还会遍历原型链上的属性!
🔑 关键点:for...of 只能用于可迭代对象,它使用的是“迭代器协议”!
🧩 三、深入 entries():优雅地同时拿到索引 + 值
const arr = ['a', 'b', 'c'];
for (const [index, value] of arr.entries()) {
console.log(index, value);
}
输出:
0 "a"
1 "b"
2 "c"
它到底做了啥?
console.log(arr.entries());
// Array Iterator {}
它返回的是一个 迭代器对象,可以用 for...of 进行遍历。
你也可以手动“慢慢迭代”:
const iter = arr.entries();
console.log(iter.next()); // { value: [0, 'a'], done: false }
console.log(iter.next()); // { value: [1, 'b'], done: false }
console.log(iter.next()); // { value: [2, 'c'], done: false }
console.log(iter.next()); // { value: undefined, done: true }
🎣 四、迭代器是啥?一文讲透
1️⃣ 什么是迭代器?
迭代器(Iterator)是一种对象协议,它规定一个对象要拥有
next()方法,每次调用返回一个{ value, done }对象。
const iterator = {
next: function () {
return { value: '🍕', done: false };
}
};
2️⃣ 所有可用 for...of 的对象,本质都是实现了迭代器协议!
比如数组的 [Symbol.iterator]:
const arr = [1, 2, 3];
const iter = arr[Symbol.iterator]();
console.log(iter.next()); // { value: 1, done: false }
🌈 五、Array.from() VS new Array()
Array.from({ length: 3 }, (_, i) => i); // ✅ 安全
new Array(3).map((_, i) => i); // ❌ 无效,因为是“空槽数组”
✅ 推荐用 Array.from() 生成指定长度数组:
const AtoZ = Array.from({ length: 26 }, (_, i) => String.fromCodePoint(65 + i));
项目场景:用于生成字母索引表、模拟分页按钮等。
🔐 六、Object.hasOwnProperty 与数组的坑
数组其实是对象,for...in 会枚举继承来的属性:
Array.prototype.hello = '🌍';
for (let key in arr) {
if (arr.hasOwnProperty(key)) {
console.log(key); // "0", "1", "2"
}
}
面试高频问题:
for...in适合对象,数组请用for...of!
🧬 七、obj.__proto__ = otherObj 是什么鬼?
这是设置对象的原型链指向:
const obj = {};
const base = { greet: () => console.log('Hi!') };
obj.__proto__ = base;
obj.greet(); // "Hi!"
⚠️ 不推荐这么用,推荐用 Object.create()、Object.setPrototypeOf() 更语义化。
🧪 八、数组遍历方式汇总 & 性能建议
| 方法 | 是否中断 | 是否拿索引 | 是否异步 | 常见场景 |
|---|---|---|---|---|
for | ✅ | ✅ | ❌ | 性能敏感、大数据处理 |
forEach() | ❌ | ✅ | ❌ | DOM 操作、日志 |
map() | ❌ | ✅ | ❌ | 生成新数组 |
filter() | ❌ | ✅ | ❌ | 条件筛选 |
reduce() | ❌ | ✅ | ❌ | 求和、分组、合并 |
for...of | ✅ | ❌ | ❌ | 配合 entries() 或迭代器 |
entries() + 解构 | ✅ | ✅ | ❌ | UI渲染、需要索引的遍历 |
🎁 实战案例:使用 entries() 做一个小表格渲染
const fruits = ['🍎', '🍊', '🍇'];
for (const [index, fruit] of fruits.entries()) {
console.log(`第${index + 1}个是:${fruit}`);
}
🔚 总结:数组进阶的修仙路线
✅ 用 for...of 代替传统 for 循环,让代码更现代
✅ 用 entries() 配合解构,一行同时拿索引和值
✅ 理解迭代器协议,掌握数据结构的底层原理
✅ 用 Array.from() 安全地构造数组
✅ 面试别再搞混 for...in 和 for...of!
🧠 一句话记忆:
for...of用于值,entries()拿索引,迭代器撑起一切遍历的底层结构!
📌 如果这篇文章对你有帮助,欢迎三连支持 + 关注我,我会继续输出更多 JS 核心知识、React 项目实战和面试通关秘籍!