javascript中数组的创建方式决定其是否为真数组:字面量[]和new array()创建的实例原型链指向array.prototype,具备完整数组特性;而object.create(array.prototype)或手动改__proto__仅继承方法,无length自动更新等内部机制,array.isarray()返回false。

JavaScript 中数组的创建方式直接影响其原型链结构,而原型链又决定了数组能调用哪些方法、是否具备数组特性(如 length 自动更新、索引赋值行为等)。理解这两者的关联,是避免“看似数组却不能用 push”或“Array.isArray() 返回 false”等问题的关键。
数组字面量与 new Array() 创建的实例都继承自 Array.prototype
无论用 [] 还是 new Array(1, 2, 3) 创建,得到的对象都是 Array 构造函数的实例,其 __proto__ 指向 Array.prototype,再向上指向 Object.prototype,最终到 null。
-
const arr = [];→arr.__proto__ === Array.prototype为true -
const arr2 = new Array('a', 'b');→ 同样满足上述关系 - 因此它们都能正常使用
map、filter、push等原生方法,且Array.isArray(arr)返回true
手动设置 __proto__ 或使用 Object.create() 不会生成真正的数组
如果仅让一个对象的原型指向 Array.prototype,它缺乏数组的内部机制(如特殊的索引属性描述符、length 的自动响应逻辑),不是规范意义上的数组。
-
const fakeArr = Object.create(Array.prototype); fakeArr[0] = 'x';→fakeArr.length仍为0(不会自动更新) -
fakeArr.push('y')虽可执行(因继承了push方法),但可能行为异常(例如未正确维护length) -
Array.isArray(fakeArr)返回false,因为该方法检测的是对象是否由Array构造函数构造
类数组对象(array-like object)不继承自 Array.prototype,但可通过借用方法使用数组能力
常见如 arguments、NodeList、{0: 'a', 1: 'b', length: 2} 等对象,它们有数字索引和 length 属性,但原型是 Object.prototype,不是 Array.prototype。
- 不能直接调用
forEach、slice等方法(除非显式借用) - 可用
Array.prototype.slice.call(obj)或更现代的[...obj]/Array.from(obj)转为真数组 -
Array.from()内部会检查obj[Symbol.isConcatSpreadable]和obj.length,并创建新数组实例,确保继承关系正确
扩展数组时需注意原型链与构造器一致性
若自定义类继承 Array(如 class MyArray extends Array),实例仍为真数组,Array.isArray() 返回 true,且 push、length 等行为保持原生语义。
- ES6 类继承会自动处理原型链:子类实例的
__proto__指向MyArray.prototype,而MyArray.prototype.__proto__指向Array.prototype - 必须使用
super()在构造器中初始化数组内部状态,否则length等可能异常 - 避免直接修改
Array.prototype—— 影响全局所有数组,且在严格模式下可能报错
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











