咨询:JavaScript对象初始化时引用自身属性为何报错?
为什么
var obj={'A':'B','C':obj['A']};会报错? 兄弟,这个问题本质是JavaScript对象字面量的执行时序在搞事情,咱们一步步拆解清楚:
核心原因:对象还没赋值给obj,就提前引用了obj
当你写var obj = { ... }的时候,整个过程是分两步的:
- JS引擎先在内存里创建一个空对象,然后按顺序处理大括号里的每个属性(把键值对逐个添加到这个空对象上)。
- 只有当所有属性都处理完、对象完全构建好之后,才会把这个对象赋值给
obj变量。
所以在处理C: obj['A']这行代码时,obj变量还没有指向正在构建的这个对象——它此时要么是undefined(如果是第一次声明obj),要么是之前的旧值。这时候你去取obj['A'],自然会得到undefined,甚至直接报错。
你的测试代码为啥先打印B、A再报错?
看你写的测试代码:
var f=function(str){ console.log(str); return str; }; var obj={ [f('A')]:[f('B')], "C":obj['A'] };
这里的执行顺序是:
- 处理第一个属性
[f('A')]:[f('B')]:- 先计算属性名:执行
f('A'),打印A,返回字符串'A'作为键。 - 再计算属性值:执行
f('B'),打印B,返回数组['B']作为值。 - 把
'A': ['B']添加到正在构建的对象上。
- 先计算属性名:执行
- 然后处理第二个属性
"C":obj['A']:- 计算属性值时引用
obj['A'],但此时obj还没被赋值为刚才的对象,所以obj是undefined,访问undefined['A']直接报错。
- 计算属性值时引用
你说先打印B、A,可能是代码里写反了f('A')和f('B')的位置,但不管顺序如何,核心问题都是obj还没指向当前对象就被引用了。
解决方法
根据你的需求,有几种靠谱的方案:
方案1:先创建对象,再补加C属性
最直接的方式,等对象完全赋值给obj后,再给C赋值:
var obj = { 'A': 'some complex function returns a string' }; obj.C = obj.A; // 或者 obj['C'] = obj['A']
方案2:用getter实现动态同步(如果需要C跟随A变化)
如果希望C的值能自动跟着A更新,可以用对象的getter方法:
var obj = { 'A': 'some complex function returns a string', get C() { return this.A; // 这里的this指向当前对象,没问题 } }; // 之后修改obj.A,obj.C也会自动变化 obj.A = 'new value'; console.log(obj.C); // 输出 'new value'
方案3:提前把A的值存到变量里
如果只是一次性复制,不想后续同步,可以先把A的计算结果存到变量中,再给对象的两个属性赋值:
const aValue = 'some complex function returns a string'; var obj = { 'A': aValue, 'C': aValue };
内容的提问来源于stack exchange,提问作者ocomfd




