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

KGr*_*ber 3 javascript variables javascript-objects

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

假设我们创建一个对象,a然后设置b = a

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

var b = a;
Run Code Online (Sandbox Code Playgroud)

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

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


我对以下情况也有疑问。

var x = 10;
var z = x;
Run Code Online (Sandbox Code Playgroud)

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

谢谢!

Sco*_*cus 6

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

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


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

  • 布尔值
  • 空值
  • 未定义
  • 符号

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

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
Run Code Online (Sandbox Code Playgroud)

当您使用引用类型时,会有些不同。将变量分配给引用类型意味着该变量仅保存对对象实际存储位置的引用,而不是对实际对象本身的引用。因此,当您这样做时:

var a = {foo:"bar"};
Run Code Online (Sandbox Code Playgroud)

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

但是,只要将另一个变量设置为与第一个变量相等,它仍然可以像处理原语一样工作 - 制作第一个变量的副本并将其提供给第二个变量。

这是一个例子:

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


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

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


ste*_*rgh 5

在你的第一种情况下:

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

var b = a;
a = {}
Run Code Online (Sandbox Code Playgroud)

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

  • 您使用数据在内存地址 0x1234 创建一个对象

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

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

  • 然后该指针被复制到b

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

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

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