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

Javascript: order of parent/child object instantiation

本文关键字:实例化 顺序 对象 Javascript      更新时间:2023-09-26

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

在代码中(一次处理一个问题):

var parent = {
  child: {
    field1: "value1",
    field2: "value2"
  },
  someOtherField: parent.child.field1 // => Error
};

在执行任何代码之前,将创建变量级并将其初始化为未定义(所谓的"提升")。一旦执行开始,对渐进结果的检查似乎是首先将对象分配给对象,然后解析内部属性。

所以第一条错误消息是这样的:

TypeError: undefined is not an object (evaluating 'parent.child.field1')

因为父级是一个对象。从此结果中,无法判断父属性是否具有属性,因为它可能具有初始化为 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

this的值将是全局对象(浏览器中的窗口),并且它没有属性,因此您会收到类似的错误:

TypeError: undefined is not an object (evaluating 'this.child.field1')

由于没有全局子项,因此 this.child 返回未定义,尝试解析未定义的属性会引发类型错误。

另请注意:

  someOtherField: this.parent.child.field1

相当于:

  someOtherField: parent.child.field1

并抛出相同的错误。

底线是,不应尝试分配部分完成的对象的属性。我确定 ECMA-262 中有适当的参考,需要一点时间才能找到它。

这与父/子对象实例化无关。它与吊装有关。

JavaScript 中的所有声明都被提升。请记住,变量声明和变量定义是两个不同的东西。例如,我们可以使用 var x 声明一个变量x。我们使用x = someValue定义x。我们可以将变量声明和变量定义组合到一个构造中,作为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.child.field1之后),才定义parent

您可以做的是:

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

希望有帮助。