Javascript:父/子对象实例化的顺序

时间:2015-01-06 02:55:56

标签: javascript

我是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是非法的。有人可以分享一些关于为什么会发生这种情况的见解,以及指令的确切顺序是浏览器尝试运行上面的代码片段吗?谢谢!

2 个答案:

答案 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.field1undefined.child.field1,这是一个错误。 this也没有指向对象字面值。你的错误是在将对象文字分配给变量之后(parent被评估之后)才定义parent.child.field1

你能做的是:

var parent = {
  child: {
    field1: "value1",
    field2: "value2"
  }
};

parent.someOtherField = parent.child.field1;

希望有所帮助。