for...in 不适合遍历数组,因为它会枚举所有可枚举属性(包括原型链上的方法和自定义字符串键),且不保证遍历顺序。

JavaScript 数组不是特殊类型,而是 Array 构造函数的实例,本质是键为数字索引、具有自动维护 length 属性的对象。
为什么 for...in 不适合遍历数组
它会枚举所有可枚举属性(包括原型链上新增的方法或意外挂载的字符串键),且不保证顺序:
const arr = [10, 20]; arr.custom = 'test'; Array.prototype.hello = 'world';for (let key in arr) { console.log(key); // 可能输出 '0', '1', 'custom', 'hello' }
- 用
for...of或传统for (let i = 0; i 遍历元素值 - 用
Object.keys(arr)获取纯数字索引(但返回的是字符串,需转数字) -
for...in真正适用场景是遍历普通对象的键名,不是数组
map、filter、reduce 的核心区别和误用点
三者都创建新数组(不修改原数组),但语义和返回值完全不同:
-
map:一对一转换,返回与原数组等长的新数组;回调必须有返回值,否则填undefined -
filter:筛选,返回满足条件的元素组成的新数组;回调返回布尔值,false/0/null/空字符串都会被过滤掉 -
reduce:聚合,返回单个值(如总和、对象、新数组);必须提供初始值(尤其处理空数组时),否则首项作初始值易出错
const nums = [1, 2, 3]; nums.map(x => x * 2); // [2, 4, 6] nums.filter(x => x > 1); // [2, 3] nums.reduce((sum, x) => sum + x, 0); // 6
修改原数组的 5 个方法及其副作用风险
这些方法直接改变 arr.length 和元素位置,可能引发意外交互:
立即学习“Java免费学习笔记(深入)”;
-
push/pop:尾部增删 —— 安全,性能好 -
unshift/shift:头部增删 —— 会重排所有索引,大数据量时明显变慢 -
splice:任意位置增删改 —— 第二参数为删除数量,若传0则只插入;返回被删除的元素数组,不是原数组
常见坑:arr.splice(0, arr.length) 清空数组,但比 arr.length = 0 或 arr = [] 更重;后者中 arr = [] 是重新赋值,不改变原引用,要注意闭包或外部变量是否还持有旧数组。
判断是不是真数组的可靠方式
typeof [] === 'object' 无法区分数组和普通对象,instanceof Array 在跨 iframe 场景下会失效:
- 首选
Array.isArray(arr)—— ES5+ 标准、全环境兼容 - 次选
Object.prototype.toString.call(arr) === '[object Array]'—— 兼容 IE6+ - 避免用
arr.constructor === Array—— 构造函数可能被改写
稀疏数组(如 [1, , 3])和带非数字属性的类数组(如 {0:1, 1:2, length:2})容易混淆,操作前务必确认类型。











