从数组菜鸟到遍历大师:entries、迭代器和数组奇技淫巧一本通(JavaScript 数组你真的掌握了吗?)

89 阅读3分钟

前端成长路线第 N 章:当你觉得你已经掌握了数组,其实只是你没见过它“进阶形态”的模样。
今天这篇文章,就带你系统梳理数组的使用细节 + 面试必考 + 源码分析 + 实战技巧


🪜 前言:数组初学者的“自我安慰”

你可能学会了这些:

const arr = [1, 2, 3];
arr.forEach(v => console.log(v));

你可能也听过这些:

arr.map()
arr.filter()
arr.reduce()

但你真的理解:

  • entries() 有多香?
  • for...infor...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...infor...of


🧠 一句话记忆:

for...of 用于值,entries() 拿索引,迭代器撑起一切遍历的底层结构!


📌 如果这篇文章对你有帮助,欢迎三连支持 + 关注我,我会继续输出更多 JS 核心知识、React 项目实战和面试通关秘籍!