JS一维对象数组按二维访问为何改底层对象?代码属性排序疑问
解答你的两个JavaScript问题
问题1:为何尝试将一维对象数组当作二维数组访问时会修改底层对象?
这里核心要搞懂JavaScript里的引用类型特性:当你把一个对象放进数组时,数组并没有存下整个对象的副本,而是存了一个指向这个对象的「引用」——你可以把它理解成对象在内存里的“地址”。
看你的代码:
const arr = new Array(1); arr[0] = {x: "first", y: "second"};
此时arr[0]里装的不是那个{x: "first", y: "second"}对象本身,只是指向它的地址。当你执行arr[0][5] = "third"时,其实是通过这个地址找到内存里的原对象,直接给它新增了一个属性5。本质上你修改的就是最初的那个对象,数组里的引用只是帮你定位到它而已,所以底层对象自然会被改动,数组打印出来也会同步显示这个变化。
简单总结:数组里的对象是“指向原对象的指针”,不是独立的复制版,通过数组访问修改,就是直接修改原对象。
问题2:为何结果中"5: 'third'"出现在对象开头?JavaScript底层如何处理?
这是因为JavaScript对象的属性有特定的排序规则,不是完全按插入顺序来的,具体规则如下:
- 第一优先级:「整数索引属性」——也就是能转换成无符号32位整数的键(比如
5,或者字符串形式的"5"),这类属性会按数值升序排列,放在对象属性的最前面; - 第二优先级:「非整数的字符串属性」——比如
"x"、"y"这类,它们严格按照插入顺序排列; - 最后是Symbol类型的属性,同样按插入顺序排列。
你的代码里,5属于整数索引属性,而x、y是非整数的字符串属性,所以打印对象时,引擎会先输出整数索引的5: "third",再按插入顺序输出x和y。
底层实现上,像V8这类JS引擎会把对象属性分成不同存储区域:整数索引属性存在类似数组的结构里,方便快速按数值访问;非整数的字符串属性则存在有序哈希表中,保留插入顺序。当遍历或打印对象时,引擎会先遍历整数索引属性(升序),再遍历字符串属性(插入顺序),最后处理Symbol属性。
内容的提问来源于stack exchange,提问作者Ramy
相关产品推荐
相关产品推荐

