对象引用如何在 javascript 内部工作

How do object references work internally in javascript

本文关键字:内部 工作 javascript 对象引用      更新时间:2023-09-26

我对javascript很陌生。我编写了简单的代码:

var temp = {}
var arr = []
temp['a'] = ['a']
arr.push(temp)
console.log(arr);

正如预期的那样,它打印:

[ { a: [ 'a' ] } ]

但是,当我将以下行附加到前面的代码时:

temp['b'] = ['b']
arr.push(temp);
console.log(arr);

我本来希望它打印:

[ { a: [ 'a' ] }, { a: [ 'a' ], b: [ 'b' ] } ]

但它打印:

[ { a: [ 'a' ], b: [ 'b' ] }, { a: [ 'a' ], b: [ 'b' ] } ]

意外结果的完整代码: var temp = {} var arr = []

temp['a'] = ['a']
arr.push(temp)
console.log(arr);
temp['b'] = ['b']
arr.push(temp);
console.log(arr);

为什么数组的第一个元素被更新了?

以下代码给了我预期的结果:

var temp = {}
var arr = []
temp['a'] = ['a']
arr.push(temp)
console.log(arr);
temp = {};
temp['a'] = ['a']
temp['b'] = ['b']
arr.push(temp);
console.log(arr);

添加temp = {}在这里有什么帮助?

Javascript 中的对象是通过引用传递的。 也就是说,只创建一个对象,并且可以使用表示该对象的符号,但它将始终引用同一对象。

让我们更深入地了解一下:

如果我理解你的例子是正确的,这部分

var temp = {}
var arr = []
temp['a'] = ['a']
arr.push(temp)
console.log(arr);
创建要向其

添加['a']的局部变量temp。 然后你把它推到arr。

因此,此时,arr引用对象temp,如下所示:

[ { a: [ 'a' ] } ]

执行此操作时:

temp['b'] = ['b']
arr.push(temp);
console.log(arr);

指向包含['a']的原始对象的temp符号将更新,因此arr也将更新,因此arr此时包含以下内容:

[ { a: [ 'a' ], b: [ 'b' ] }, { a: [ 'a' ], b: [ 'b' ] } ]

最后

然后改为执行以下操作:

temp = {};
temp['a'] = ['a']
temp['b'] = ['b']
arr.push(temp);
console.log(arr);

这将创建一个单独的全局变量temp,您将两者添加到该变量上 ['a']['b'] . 这是全局的,因为它在声明/初始化中没有 var 关键字。 然后这被推入arr。 但是,由于它是一个全局变量而不是原始局部变量,因此您会看到以下内容:

 [ { a: [ 'a' ] }, { a: [ 'a' ], b: [ 'b' ] } ]
在第

一种情况下,arr[0]temp的引用,arr[1]也有temp的引用。因此,arr[0]arr[1]具有相同的参考。

因此,更新引用将在引用所在的任何位置更新它被推荐。

但是,在第二种情况下,当您执行temp = {}时,您只需在推送新引用之前将temp重新分配给引用。因此,arr[0]的引用之间没有关系,因此现在更新temp只会影响它。

例子不一样,与temp = {}无关。

在第一个示例中,您按temp两次,这意味着arr必须引用 2 temp

在第一个push之后,您将另一个项目添加到temp,因此在arr 中,如果您打印了它,您将看到:

[ { a: [ 'a' ], b: [ 'b' ] } ]

因此,请在控制台上尝试一下:

var temp = {}
var arr = []
temp['a'] = ['a']
arr.push(temp)
temp['b'] = ['b']
console.log(arr);

您将看到结果:

[ { a: [ 'a' ], b: [ 'b' ] } ]

将另一个temp推入arr只会导致两个引用进入temp

JavaScript 中有两种数据类型 - 值类型和引用类型。

值类型实际上是在对象之间发送时复制的。这是因为这是您对某些事物(如数字和布尔值)的期望。

假设我将数字1传递给一个函数,该函数将其存储在对象A中。

如果我随后可以通过修改原始数字的值来修改A中包含的值,那将是令人惊讶的。因此,按值传递。还可以对值类型执行优化。

对象(即除数字文字、布尔文字、null、undefined 和字符串文字*之外的所有内容)是 JavaScript 中的引用类型,只有它们的引用被传递。这主要是出于效率原因。在您的示例中,temp是一个对象。因此,它通过引用传递。

所以

temp['b'] = ['b']

修改 temp 的单个现有实例,从而修改 arr 的内容,然后再再次将temp推送到arr

所以你最终得到一个数组,其中包含对单个对象temp的两个引用,给你观察到的结果。

* 字符串实现有一些复杂性,我在这里故意忽略了这些复杂性。