JavaScript 的 Array 是继承自 Object.prototype 的特殊对象,具有内部槽[[ArrayLength]]、稀疏索引机制和专属原型方法;它本质是键值对容器,仅对数字字符串键做优化;Array.isArray() 是唯一可靠判断方式,for...of等迭代行为依赖其数组语义,而 TypedArray 才更接近传统连续内存数组。

JavaScript 的 Array 是对象,但不是「普通对象」
因为 Array 构造函数返回的是继承自 Object.prototype 的特殊对象,它有内部槽 [[ArrayLength]] 和稀疏索引处理机制,同时拥有专属的原型方法(如 push、map)。它不是 C 或 Java 那种连续内存块上的“真数组”,而是一个键值对容器,只是对数字字符串键做了特殊优化和语义约定。
Array.isArray() 是唯一可靠判断方式
用 typeof [] === 'object' 或 instanceof Object 都无法区分数组和普通对象,甚至 instanceof Array 在跨 iframe 场景下会失效。只有 Array.isArray() 能穿透所有边界准确识别。
const arr = [];
const obj = {};
console.log(Array.isArray(arr)); // true
console.log(Array.isArray(obj)); // false
console.log(Array.isArray({0: 'a', length: 1})); // false —— 伪数组不是数组
数组的「数字索引」行为与普通对象属性有本质差异
当你写 arr[100] = 'x',JavaScript 引擎会更新内部 [[ArrayLength]] 槽(可能扩大长度),并触发 length 属性的 getter/setter;而 obj['100'] = 'x' 只是存一个字符串键,不改变任何长度语义。这种差异直接影响 for...of、map、forEach 等迭代行为。
-
arr.length是动态计算的:取决于最大整数索引 + 1,且可被显式修改(如arr.length = 0清空) -
obj.length不存在(除非手动加),Object.keys(obj)不保证顺序,也不识别数字键的“数组性” - 稀疏数组(如
[1,,3])中in操作符和hasOwnProperty表现不同:缺失项既不占内存,也不被forEach访问,但1 in arr是false
TypedArray 才更接近传统意义的「真数组」
如果你需要内存连续、固定类型、不可动态扩容的数组,应该用 Uint8Array、Float64Array 等 TypedArray。它们不是 Array 的子类,没有 push 方法,length 是只读的,底层绑定 ArrayBuffer,性能和行为都更接近系统级数组。
立即学习“Java免费学习笔记(深入)”;
const typed = new Uint8Array(3); typed[0] = 255; typed.length = 5; // 无效,length 不可变 console.log(Array.isArray(typed)); // false
真正容易被忽略的是:日常写的 [] 从不保证内存连续,V8 等引擎会根据使用模式在「快数组」「慢数组」「字典模式」间切换——你写的 push 很可能某天就触发了哈希表降级,性能跳变却毫无提示。











