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

时间:2021-08-28 16:54:07

I am very new to javascript. I have written the simple code:

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

var temp = {}
var arr = []

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

As expected, it prints:

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

[ { a: [ 'a' ] } ]

But then, when I append the following line to the previous code:

但是,当我在之前的代码中添加以下一行时:

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

I would have expected it to print:

我希望它能印出来:

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

But it prints:

但它打印:

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

Entire code for unexpected result: var temp = {} var arr = []

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

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

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

Why did the first element of array got updated?

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

The following code gave me expected result:

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

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);

How does adding temp = {} helped here?

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

4 个解决方案

#1


2  

Objects in Javascript are passed by reference. That is, only one object is created and the symbol that represents that object can be used but it will refer to the same object always.

Javascript中的对象通过引用传递。也就是说,只有一个对象被创建,而代表该对象的符号可以被使用,但它总是指向同一个对象。

Lets take a deeper look:

让我们更深入地看看:

If I'm understanding your example correct, this part

如果我理解正确的话,这一部分

var temp = {}
var arr = []

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

Creates a local variable temp to which you add ['a'] to. You then push that into arr.

创建一个本地变量temp,并向其添加['a']。然后把它推入arr。

So at this point, arr references the object temp and looks like this:

在这一点上,arr引用了对象temp,看起来是这样的:

[ { a: [ 'a' ] } ]

When you do this:

当你这样做:

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

The temp symbol which points to the original object containing ['a'] is updated, and so the arr will also get updated, so arr contains this at that point:

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

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

Finally,

最后,

You then do this instead:

你可以这样做:

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

This creates a separate global variable temp, onto which you add both ['a'] and ['b']. This is global because it does not have the var keyword in the declaration/initialization. This then gets pushed into the arr. However, since it's a global variable and not the original local variable, you see this instead:

这将创建一个单独的全局变量temp,您可以在其中添加['a']和['b']。这是全局的,因为它在声明/初始化中没有var关键字。这就会被推入到arr中。但是,由于它是一个全局变量,而不是原始的局部变量,所以您看到的是:

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

#2


1  

In first case, arr[0] has temp's reference, arr[1] also has temp's reference. So, arr[0] and arr[1] have the same reference.

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

Hence updating the reference will update it everywhere where the reference is being referred.

因此,更新引用将在引用被引用的任何地方更新它。

In second case however, when you do temp = {} you're just reassigning temp to a new reference, before pushing it. So, there's no relationship between the arr[0]'s reference, and hence updating temp now, only affects it.

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

#3


1  

There are two data types in JavaScript - value types and reference types.

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

Value types are actually copied as they are sent between objects. This is because this is what you would expect for certain things like numbers and booleans.

值类型实际上是在对象之间发送时复制的。这是因为这是你对数字和布尔值的期望。

Say I pass the number 1 to a function that stores it in an object A.

假设我将数字1传递给存储在对象a中的函数。

It would be surprising if I could then subsequently modify the value contained in A simply by modifying the value of the original number. Hence, pass by value. There are also optimizations that can be performed for value types.

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

Objects (i.e. everything other than number literals, boolean literals, null, undefined, and string literals*) are reference types in JavaScript and only their reference is passed around. This is largely for efficiency reasons. In your example, temp is an object. It is therefore passed by reference.

对象(也就是说,除了数字常量、布尔常量、null、undefined和字符串常量*之外的所有对象都是JavaScript中的引用类型,只有它们的引用才会被传递。这主要是出于效率的原因。在您的示例中,temp是一个对象。因此,它是通过引用来传递的。

And so

所以

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

Modifies the single existing instance of temp, thereby modifying the contents of arr, before you then also push temp into arr for a second time.

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

So you end up with an array containing two references to a single object temp, giving you the observed result.

因此,您最终得到一个数组,该数组包含对单个对象temp的两个引用,并给出所观察到的结果。

* There is some complexity surrounding the string implementation that I am purposefully ignoring here.

*我有意忽略的字符串实现有一些复杂性。

#4


0  

The examples are not the same, it doesn't have to do with temp = {}.

这些例子并不相同,它与temp ={}没有关系。

In the first example you push temp twice, meaning arr has to references 2 temp.

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

After the first push you add another item to temp so within arr, if you had print it, you would have seen:

在第一次推送之后,你在arr中添加了另一个项目,如果你打印了,你就会看到:

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

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

So try this out on the console:

所以在控制台试试这个:

var temp = {}
var arr = []

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

You'll see the result:

你会看到结果:

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

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

Pushing another temp into arr is just going to result into two references into temp.

将另一个temp推入arr只会导致两个对temp的引用。

#1


2  

Objects in Javascript are passed by reference. That is, only one object is created and the symbol that represents that object can be used but it will refer to the same object always.

Javascript中的对象通过引用传递。也就是说,只有一个对象被创建,而代表该对象的符号可以被使用,但它总是指向同一个对象。

Lets take a deeper look:

让我们更深入地看看:

If I'm understanding your example correct, this part

如果我理解正确的话,这一部分

var temp = {}
var arr = []

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

Creates a local variable temp to which you add ['a'] to. You then push that into arr.

创建一个本地变量temp,并向其添加['a']。然后把它推入arr。

So at this point, arr references the object temp and looks like this:

在这一点上,arr引用了对象temp,看起来是这样的:

[ { a: [ 'a' ] } ]

When you do this:

当你这样做:

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

The temp symbol which points to the original object containing ['a'] is updated, and so the arr will also get updated, so arr contains this at that point:

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

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

Finally,

最后,

You then do this instead:

你可以这样做:

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

This creates a separate global variable temp, onto which you add both ['a'] and ['b']. This is global because it does not have the var keyword in the declaration/initialization. This then gets pushed into the arr. However, since it's a global variable and not the original local variable, you see this instead:

这将创建一个单独的全局变量temp,您可以在其中添加['a']和['b']。这是全局的,因为它在声明/初始化中没有var关键字。这就会被推入到arr中。但是,由于它是一个全局变量,而不是原始的局部变量,所以您看到的是:

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

#2


1  

In first case, arr[0] has temp's reference, arr[1] also has temp's reference. So, arr[0] and arr[1] have the same reference.

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

Hence updating the reference will update it everywhere where the reference is being referred.

因此,更新引用将在引用被引用的任何地方更新它。

In second case however, when you do temp = {} you're just reassigning temp to a new reference, before pushing it. So, there's no relationship between the arr[0]'s reference, and hence updating temp now, only affects it.

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

#3


1  

There are two data types in JavaScript - value types and reference types.

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

Value types are actually copied as they are sent between objects. This is because this is what you would expect for certain things like numbers and booleans.

值类型实际上是在对象之间发送时复制的。这是因为这是你对数字和布尔值的期望。

Say I pass the number 1 to a function that stores it in an object A.

假设我将数字1传递给存储在对象a中的函数。

It would be surprising if I could then subsequently modify the value contained in A simply by modifying the value of the original number. Hence, pass by value. There are also optimizations that can be performed for value types.

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

Objects (i.e. everything other than number literals, boolean literals, null, undefined, and string literals*) are reference types in JavaScript and only their reference is passed around. This is largely for efficiency reasons. In your example, temp is an object. It is therefore passed by reference.

对象(也就是说,除了数字常量、布尔常量、null、undefined和字符串常量*之外的所有对象都是JavaScript中的引用类型,只有它们的引用才会被传递。这主要是出于效率的原因。在您的示例中,temp是一个对象。因此,它是通过引用来传递的。

And so

所以

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

Modifies the single existing instance of temp, thereby modifying the contents of arr, before you then also push temp into arr for a second time.

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

So you end up with an array containing two references to a single object temp, giving you the observed result.

因此,您最终得到一个数组,该数组包含对单个对象temp的两个引用,并给出所观察到的结果。

* There is some complexity surrounding the string implementation that I am purposefully ignoring here.

*我有意忽略的字符串实现有一些复杂性。

#4


0  

The examples are not the same, it doesn't have to do with temp = {}.

这些例子并不相同,它与temp ={}没有关系。

In the first example you push temp twice, meaning arr has to references 2 temp.

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

After the first push you add another item to temp so within arr, if you had print it, you would have seen:

在第一次推送之后,你在arr中添加了另一个项目,如果你打印了,你就会看到:

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

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

So try this out on the console:

所以在控制台试试这个:

var temp = {}
var arr = []

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

You'll see the result:

你会看到结果:

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

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

Pushing another temp into arr is just going to result into two references into temp.

将另一个temp推入arr只会导致两个对temp的引用。