设置一个变量等于另一个变量

IT技术 javascript variables javascript-objects
2021-02-25 12:18:58

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

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

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

var b = a;

我知道如果我们更改a的属性之一b也会更改,因为当我们设置时,b = a我们不会克隆a的数据,而是创建对a数据的引用例如,如果我们设置a.fname = "Sarah", 的新值b.fname将是"Sarah"

如果我们尝试a通过设置来“清除” a = {},对象b将保持不变。我不明白为什么以这种方式操作对象会产生与第一个示例不同的结果。


另外我对以下场景有疑问。

var x = 10;
var z = x;

如果我们然后设置x = 20, 的值z保持不变。根据我在第一个问题中描述的行为,人们会认为 的新值z将反映 的新值x有人可以解释一下我在这里缺少什么吗?

谢谢!

3个回答

对你的两个问题的真正简短的回答是,当你使一个变量等于另一个变量时,第一个变量中的内容被复制并存储在第二个变量中- 这两个变量之间没有链接。

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


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

  • string
  • 数字
  • 布尔值
  • 空值
  • 不明确的
  • 象征

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

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

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

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别的东西。

如何通过 COPY 而不是 REFERENCE 分配对象的 var ?更新:找到了我的问题的答案:stackoverflow.com/questions/40133582/...
2021-04-28 12:18:58

让我试着解释一下:

1) 在您的示例中,aandb是对同一个对象的引用,而a.fname(或b.fname) 是该对象的一个​​属性。所以当操作属性时,它会在对象中改变,而引用不会受到影响,它们仍然指向同一个对象,对象本身已经改变了。a = {}另一方面,只会替换对对象的引用,而不会影响对象本身或b对 It 的引用。
顺便说一句,您只是创建了一个对新空对象的新引用,这并不重要。

2)这些不是对象,因此没有直接操作值的参考。那是因为对象和原语之间存在差异,如果您不习惯使用严格类型,这可能会使您感到困惑,尤其是在开始时。

在你的第一种情况下:

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仍然指向它。

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