我是JavaScript新手,想了解更多关于实例化父/子对象的顺序。更具体地说,我想从编译器/浏览器的角度理解以下片段。
var parent = {
child: {
field1: "value1",
field2: "value2"
},
someOtherField: parent.child.field1, // => Error
someOtherField: this.child.field1 // => Error
};
上面代码段中的Error
行都会生成相同的错误
Uncaught TypeError: Cannot read property 'field1' of undefined
因此,当浏览器查看someOtherField
行时,parent.child
仍然是undefined
,因此parent.child.field1
是非法的。有人可以分享一些关于为什么会发生这种情况的见解,以及指令的确切顺序是浏览器尝试运行上面的代码片段吗?谢谢!
答案 0 :(得分:1)
在代码中(一次处理一个问题):
var parent = {
child: {
field1: "value1",
field2: "value2"
},
someOtherField: parent.child.field1 // => Error
};
在执行任何代码之前,创建变量 parent 并初始化为 undefined (所谓的" hoisting")。执行开始后,检查渐进结果似乎是首先将对象分配给 parent ,然后解析内部属性。
所以第一条错误信息如下:
TypeError: undefined is not an object (evaluating 'parent.child.field1')
因为 parent 是一个对象。从这个结果来看, parent 是否具有子属性是不可能的,因为它可能将 child 属性初始化为< em> undefined ,或者根本没有子属性。无论哪种方式,parent.child
都解析为 undefined ,并且尝试解析 undefined 的属性会返回类型错误。
请注意:
var parent = {
one: 'one',
two: parent.one
}
console.log(parent.one, parent.two) // one undefined
可以看出,在为 parent.two 分配值时, parent.one 未定义。
至于:
someOtherField: this.child.field1
此的值将是全局对象(浏览器中的窗口),并且它没有子属性,因此您会收到类似的错误:
TypeError: undefined is not an object (evaluating 'this.child.field1')
因为没有全局子,所以 this.child 返回 undefined 并尝试解析 undefined的属性抛出类型错误。
另请注意:
someOtherField: this.parent.child.field1
相当于:
someOtherField: parent.child.field1
并抛出相同的错误。
最重要的是,您不应该尝试分配部分完成的对象的属性。我确定ECMA-262中有适当的参考资料,需要一段时间才能找到它。
答案 1 :(得分:0)
这与父/子对象实例化无关。它与吊装有关。
JavaScript中的所有声明都会被提升。请记住,变量声明和变量定义是两个独立的事物。例如,我们可以使用x
声明变量var x
。我们使用x
定义x = someValue
。我们可以将变量声明和变量定义组合为单个构造var x = someValue
。但是我们仍然在声明变量然后定义变量。
正如我所说,JavaScript中的所有声明都被提升(即它们被提升到声明它们的函数作用域的顶部)。例如,考虑:
alert(x); // declared but not defined (undefined)
var x = null;
alert(x); // declared and defined (null)
此处变量声明var x
已被提升到范围的顶部。已声明但尚未定义的变量默认值为undefined
。
将上述代码与:
进行比较
try {
alert(x);
x = null;
alert(x);
} catch(e) {
alert(e); // ReferenceError: x is not defined
}
此处我们尚未声明x
。因此x
未被提升。因此,当我们尝试打印x
的值时,我们得到ReferenceError
。请注意,它不是undefined
,因为我们甚至没有声明它。
现在让我们考虑你的代码:
var parent = {
child: {
field1: "value1",
field2: "value2"
},
someOtherField: parent.child.field1 // => Error
someOtherField: this.child.field1 // => Error
};
这与:
相同var parent; // hoisted; undefined
parent = {
child: {
field1: "value1",
field2: "value2"
},
someOtherField: parent.child.field1 // => Error
someOtherField: this.child.field1 // => Error
};
在定义parent
之前,它是undefined
。因此parent.child.field1
为undefined.child.field1
,这是一个错误。 this
也没有指向对象字面值。你的错误是在将对象文字分配给变量之后(parent
被评估之后)才定义parent.child.field1
。
你能做的是:
var parent = {
child: {
field1: "value1",
field2: "value2"
}
};
parent.someOtherField = parent.child.field1;
希望有所帮助。