为何JavaScript数组通过点语法创建的属性存在但不计入array.length?
JavaScript 数组的点语法自定义属性
尽管该行为有违直觉,但我们确实可以使用点语法为JavaScript数组创建自定义「属性」:
const arr = []; arr.dot = "notation"; console.log(arr.dot); // "notation"
这种写法没有任何语法错误,运行完全合规。但实际运行中会出现一个很容易引发困惑的表现:哪怕你给数组加了自定义属性,它的length属性值也完全不会变化:
const arr = []; arr.dot = "notation"; console.log(arr.dot); // "notation" console.log(arr.length); // 0
常见核心疑问
针对这个现象,开发者通常会提出两个关键问题:
- 为什么通过点语法为数组赋值的属性不会影响数组的
length属性值? - 为什么JavaScript支持通过点语法为数组赋值自定义属性?
问题原理拆解
为什么自定义点属性不影响数组length?
JavaScript数组的length自动更新逻辑,仅对数组的「索引属性」生效:
- 索引属性的官方定义是:属性名可以被转换为32位非负整数,且数值范围在
0 ~ 2^32 - 2区间内的字符串值,比如"0"、"123"这类符合数组索引规则的属性名 - 当你通过方括号语法给数组赋值对应索引的属性时,JS引擎会自动触发联动逻辑:把数组的
length值更新为「最大索引属性值 + 1」 - 你通过点语法挂载的
dot属性名,根本无法转换为合法的数组索引,属于普通的对象自有属性,完全不参与length的计算逻辑,自然不会让length发生变化
为什么数组支持通过点语法加自定义属性?
核心逻辑非常简单:JavaScript数组本质就是叠加了特殊规则的普通对象
- JS的普通对象设计默认是动态可扩展的,只要对象没有被设置为防扩展、防修改的状态,你就可以通过点语法、方括号语法给它挂载任意名称的自定义属性
- 数组从来没有关闭这个对象的基础能力,它只是在普通对象的基础上,额外叠加了两层特殊规则:一是索引属性和
length的联动逻辑,二是原型上内置了push、pop、map等专门操作索引属性的数组方法,并没有任何设计层面的限制禁止用户给它加普通的非索引自定义属性
内容的提问来源于stack exchange,提问作者Brian Zelip
相关产品推荐
相关产品推荐

