首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JS对象按值复制与引用复制

问JS对象按值复制与引用复制
EN

Stack Overflow用户
提问于 2013-10-18 11:31:10
回答 5查看 11.7K关注 0票数 9

我在玩镀铬控制台,注意到一些我无法理解的东西。我知道在JS中,变量是通过值复制的,对象是通过引用复制的。下面的代码工作得很好,可以输出2,并证明JS对象可以作为参考:

代码语言:javascript
复制
var objA = {a: 1};
var objB = objA;
objA.a = 2; 
objB.a; // 2

然而,这段代码并不像它应该的那样工作。我期望objB.a输出2,但它却给出了1。为什么?

代码语言:javascript
复制
var objA = {a: 1};
var objB = objA;
objA = {a: 2};  //Assigned whole object here instead property.
objB.a; //1 - Shouldn't this be 2 ??
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2013-10-18 11:33:52

我宁愿把带有对象的变量看作对象的指针(比如C指针),而不是引用。

在第三行中,您刚刚替换了objA,使其“指向”另一个对象。它不会改变任何objB“指向”的内容。

在第3行,objA现在指向{a:2},而objB仍然指向在您将其分配给objB时所指向的任何objA,在第2行,即{a:1}。

代码语言:javascript
复制
line 1: objA -> {a:1}
line 2: objA -> {a:1} <- objB
line 3: objA -> {a:2}, objB -> {a:1}
票数 14
EN

Stack Overflow用户

发布于 2013-10-18 12:20:29

我喜欢把JavaScript变量看作粘性笔记。便条是你放在冰箱上的一张小纸条。你能在便条上写些什么?你可以写一些小的信息。

现在JavaScript中有两种类型的信息--原语值和引用值。原语值是你可以直接写在便笺上的小部分信息。它们包括:

  1. 布尔人
  2. 数字
  3. 字符串
  4. 空
  5. 未定义

另一方面,参考值是大量的信息,你不能在一个小便条上写。那么,如何在便笺中存储引用值呢?

你没有。

引用值(如数组、对象和函数)写在一张更大的纸上,而在便笺上只写了对它们的引用。例如,我妻子可能会写:

亲爱的,食品杂货清单在你的键盘下面。

在这里,杂货清单是一个数组(即大量的信息)。因为我们不能把它写在一张小便条上,我们只需把它写在一张更大的纸上,然后写一张便条,告诉我们在哪里可以找到它。在方案拟订方面:

代码语言:javascript
复制
var groceryList = ["1 apple", "2 bananas", "3 loaves of bread"];

在这里,实际的杂货店列表存储在内存中的某个地方,只有杂货店列表的地址存储在变量groceryList中。

那么,当我们将一个变量赋值给另一个变量时会发生什么呢?让我们首先以一个原始值为例:

代码语言:javascript
复制
var x = 2;
var y = x;
alert(y);  // 2
y = 3;
alert(x);  // 2

这就是正在发生的事情:

  1. 我们把数字2写在一张新的便条上,放在冰箱上。
  2. 我们把2号码从便笺x复制到另一个便笺y上,然后放在冰箱上。
  3. 我们删除便笺y的值,并将数字3写在上面。
  4. 现在粘性便笺x的值是2,粘性便笺y的值是3。

这被称为按值复制,因为我们只是将便笺x的值复制到便签y上。

现在让我们以一个引用复制的例子为例。实际上,让我们以引用的副本为例:

代码语言:javascript
复制
var objA = {a: 1};
var objB = objA;
objA.a = 2;
objB.a; // 2

下面是在您的示例中发生的事情:

  1. 我们在内存中的某个地方创建一个对象{a: 1},并将该对象的地址写在便签objA上。为了简单起见,让我们将这个地址称为x。
  2. 我们将地址x从便签objA复制到另一个便笺objB上。现在,objA和objB都引用存储在内存位置x中的相同对象{a: 1}。
  3. 因此,当我们更改objA.a的值时,相同的更改将反映在objB.a上,因为objA和objB都引用存储在内存位置x中的相同对象。

这被称为按引用复制,因为我们只是简单地将对象的引用从便签objA复制到粘滞便笺objB。我们不是在复制实际的物体。

那么,引用复制和按价值复制之间有什么区别呢?什么事也没有。在这两种情况下,我们只是将一张便笺的值复制到另一张便笺上。

只有当两张便条包含完全相同的信息时,它们才会被认为是等价的。例如,以下内容是等价的:

代码语言:javascript
复制
var x = 2;
var y = 2;
alert(x === y); // true

var o = {a: 1};
var p = o;
alert(o === p); // true

然而,以下值并不等价:

代码语言:javascript
复制
var o = {a: 1};
var p = {a: 1};
alert(o === p); // false

它们不等价的原因是,o指向存储在内存位置的对象,比如x,而p指向存储在不同内存位置的对象,比如y。虽然这两个对象具有完全相同的属性,但它们实际上是两个不同的对象。

例如,任天堂的两个游戏男孩都是一样的,不管他们看上去有多相同。本着同样的精神,让我们看看最后一个例子:

代码语言:javascript
复制
var objA = {a: 1};
var objB = objA;
objA = {a: 2};  //Assigned whole object here instead property.
objB.a; //1 - Shouldn't this be 2 ??

下面是上面代码中发生的情况:

  1. 我们在内存位置创建一个对象{a: 1},x并在便签objA上写入地址x。
  2. 我们将地址x从便签objA复制到便笺objB。它们现在都指向存储在内存位置x上的同一个对象。
  3. 我们在一个内存位置创建一个新的对象{a: 2},y,并在objA上写入地址y。现在,objA有一个引用值y,objB有一个引用值x。它们指的是两个不同的物体。

正如您所看到的,为objA分配一个新的引用值只是覆盖了旧的引用值。它不会将对象{a: 1}替换为对象{a: 2}。这在JavaScript中是不可能的。

票数 6
EN

Stack Overflow用户

发布于 2013-10-18 11:33:58

第一个示例的工作原理是两个变量指向的对象都是相同的。

在您的第二个示例中,没有这样做,因为您要将另一个对象分配给line #3的objA。

代码语言:javascript
复制
objA = {a: 2};  //Assigned whole object here instead property.

这将使objA指向另一个对象({a:2}),而objB将指向旧对象。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19448646

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档