将变量设置为另一个变量 - JavaScript

时间:2018-06-13 14:53:23

标签: javascript variables javascript-objects

我有一些关于在JavaScript中设置变量等于另一个变量的问题。

我们假设我们创建了一个对象a并设置了b = a

var a = {
  fname: "Jon",
  lname: "Smith",
  age: 50
}

var b = a;

我了解如果我们更改a的其中一个属性b也会更改,因为当我们设置b = a时,我们不会克隆{{1}数据,而是创建对a数据的引用。例如,如果我们设置a,则a.fname = "Sarah"的新值将为b.fname

如果我们试图清除" "Sarah"但是通过设置a,对象a = {}将保持不变。我不明白为什么以这种方式操纵对象会产生与第一个例子不同的结果。

此外,我对以下情况有疑问。

b

如果我们设置var x = 10; var z = x; ,则x = 20的值保持不变。基于我在第一个问题中描述的行为,人们会认为z的新值会反映z的新值。有人可以解释我在这里缺少的东西吗?

谢谢!

3 个答案:

答案 0 :(得分:4)

对你的两个问题的答案非常简短,当你将一个变量设为另一个变量时,第一个变量中的变量的副本被存储在第二个变量中 - 两个变量之间没有联系。

但是,请继续阅读以了解更多详细信息以及为什么在某些情况下似乎存在链接......

与许多语言一样,JavaScript将数据分为两大类:值类型和引用类型。 JavaScript值类型为 its primitives

  • 字符串
  • 布尔
  • 未定义
  • 符号

当您将任何这些类型分配给变量时,实际数据将存储在该变量中,如果您将一个变量设置为等于另一个变量,则原语的副本(不是链接)是制作并存储在新变量中:



var a = 10;  // Store the actual number 10 in the a variable
var b = a;   // Store a COPY of the actual number stored in a (10) in the b variable
a = 50;      // Change the actual data stored in a to 50 (no change to b here)
console.log(b);  // 10




当您使用 reference types 时,会发生一些不同的事情。将变量分配给引用类型意味着该变量仅保存对实际存储对象的内存位置的引用,而不是实际对象本身。所以,当你这样做时:

var a = {foo:"bar"};

a实际上并不存储对象本身,它只存储可以找到对象的内存位置(即0x3C41A)。

但是,只要设置另一个变量等于第一个变量,它仍然可以像原始数据那样工作 - - 复制第一个变量被生成并赋予第二个变量。

以下是一个例子:



// An object is instantiated in memory and a is given the address of it (for example 0x3C41A)
var a = {}; 
 
// The contents of a (the memory location of an object) is COPIED into b.
// Now, both a and b hold the same memory location of the object (0x3C41A)
var b = a;

// Regardless of whether a or b is used, the same underlying object
// will be affected:
a.foo = "test";
console.log(b.foo); // "test"

// If one of the variables takes on a new value, it won't change
// what the other variable holds:
a = "something else";
console.log(b);   // The object stored in memory location (0x3C41A)




因此,在您的第一次测试中,您只是有两种方法可以访问一个对象,然后您将a所持有的内容(对象的内存位置)更改为另一个对象,因此现在您只有一种方法可以通过b访问原始对象。

  

如果我们试图清除" a通过设置a = {},对象b将保留   不变。我不明白为什么以这种方式操纵一个物体   产生与第一个例子不同的结果。

因为现在我们知道a = {}没有清除对象。它只是将a指向别的东西。

答案 1 :(得分:2)

让我试着解释一下:

1)在您的示例中,ab是对同一个对象的引用,而a.fname(或b.fname)是该对象的属性。因此,在操作属性时,它将在对象中更改,而引用不会受到影响,它们仍然指向同一个对象,对象本身已被更改。另一方面,a = {}只会替换对象的引用,而不会影响对象本身或b对它的引用。
你只是创建了一个新的引用一个新的空对象。

2)这些不是对象,因此没有直接操作值的引用。这是因为如果您不习惯使用严格类型,那么对象和基元之间可能存在差异,尤其是在开始时可能会引起混淆。

答案 2 :(得分:1)

在你的第一个案例中:

var a = {
  fname: "Jon",
  lname: "Smith",
  age: 50
}

var b = a;
a = {}

b保持不变,因为这是在后台发生的事件序列:

  • 使用数据

    在内存地址0x1234处创建一个对象

    fname: "Jon",   lname: "Smith",   age: 50

  • 指向该内存块的指针存储在a

  • 然后将该指针复制到b

此时有两个对同一位内存的引用。更改该内存块中的任何内容都会影响对它的引用。

  • a = {}不会清除内存块0x1234,但会在另一个内存位置(0x1235)上创建一个新对象,并在a中存储指向该块的指针。 0x1234处的内存保持不变,因为b仍然指向它。

简单变量和对象/指针之间的这种内存管理存在差异。字符串和数字的种类很简单,并且“按值传递”而不是“通过引用传递”对象。