什么是javascript数组_如何遍历和操作数组元素【教程】

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 真正适用场景是遍历普通对象的键名,不是数组

mapfilterreduce 的核心区别和误用点

三者都创建新数组(不修改原数组),但语义和返回值完全不同:

  • 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 和元素位置,可能引发意外交互:

  • push/pop:尾部增删 —— 安全,性能好
  • unshift/shift:头部增删 —— 会重排所有索引,大数据量时明显变慢
  • splice:任意位置增删改 —— 第二参数为删除数量,若传 0 则只插入;返回被删除的元素数组,不是原数组

常见坑:arr.splice(0, arr.length) 清空数组,但比 arr.length = 0arr = [] 更重;后者中 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})容易混淆,操作前务必确认类型。