javascript赋值运算符数组

时间:2012-10-24 13:28:45

标签: javascript

在分配对象(比如数组)时,我不理解赋值运算符。我被告知,作为赋值运算符复制引用。然而,它似乎复制数据。例如:

var globArray = [];

function test() {
  var names = ["craig", "silva"];
  globArray = names;
}//endFunction test

function test2() {
  console.log("el1: ", globArray[0], "el2: ", globArray[1]);
}//endFunction test2

当我调用TEST时,它会创建数组NAMES并将全局数组“globArray”分配给NAMES。现在它超出了范围,所以“名字”消失了,对吧?然后我调用test2,但它会显示元素!因此,它必须使整个对象复制,而不是仅仅应对参考。

有人可以解释一下吗?

5 个答案:

答案 0 :(得分:6)

当你的“测试”功能返回时,你说“名字”已“消失”是正确的。但是,它的不是,因为它已被分配给全局变量。 “names”局部变量的是数组对象的引用。该引用被复制到全局变量中,所以现在该全局变量还包含对数组对象的引用。

对象分配是一个全局性的事情。当一个对象被局部变量分配和引用时,当局部变量在其范围变为非活动状态时消失时,它将被垃圾收集,除非存在对象的某些其他引用(直接或间接)。直接引用就像你的情况一样。如果本地范围“泄漏”包含对局部变量的引用的函数,则可能发生间接引用。

答案 1 :(得分:3)

这里有两件事情:激活记录和堆上的对象。

您从全局变量的激活框架开始:

globArray : undefined

并且堆包含出现在代码中的文字

ptr0      : "craig"
ptr1      : "silva"

其中ptr0ptr1等只是引用内存中特定位置的地址或标签。

当您致电test()时,解释程序会推送一个新的激活框,其中包含局部变量的框。

globArray : undefined
---------------------
names     : undefined

然后解释器评估在堆上创建对象的["craig", "silva"]

ptr0      : "craig"
ptr1      : "silva"
ptr2      : [ &ptr0, &ptr1 ]

所以ptr2现在是内存中一个包含指向两个值的数组的位置。

此内存位置现在存储在激活记录的names位置,因此您的调用堆栈看起来像

globArray : undefined
---------------------
names     : &ptr2

赋值names = ...不会更改堆,只会更改激活记录。

下一个globArray = names将一个激活记录条目的内容复制到另一个。

globArray : &ptr2
---------------------
names     : &ptr2

然后对test的调用结束,以便放弃激活记录,留下

globArray : &ptr2

其中全局globArray指向在调用test期间创建的对象。 函数的结尾只更改了活动的激活记录,而不是堆,因此堆仍然看起来像

ptr0      : "craig"
ptr1      : "silva"
ptr2      : [ &ptr0, &ptr1 ]

所以ptr2仍然是同一个数组。

  

所以“名字”消失了,对吧?

names(激活记录中的条目)消失了,但它指向的对象不是,因为它仍然被活动激活记录中的globArray条目指向。

  

然后我调用test2,但它会显示元素!所以它必须让COPIED整个对象

不,它只是复制了对该对象占用的堆中的位置的引用。由于未更改堆,因此没有创建新对象,并且堆是创建所有对象的位置。

What and where are the stack and heap?可能会引起人们的兴趣。

答案 2 :(得分:2)

Javascript对象被垃圾收集。

names变量引用的对象将在test()退出后继续存在,因为它仍然被全局变量引用。

答案 3 :(得分:2)

名称和globalArray都引用同一个对象。只要在范围内至少有一个对象引用,该对象就不会“消失”。你知道什么消失了吗?初始数组globalArray引用。

答案 4 :(得分:0)

该对象与保存对它的引用的变量分开。即使在变量消失之后,对象仍可能存在。这就是代码中发生的事情,即使names变量消失,它引用的对象仍然独立于变量name而存在。只有当对象没有引用时,它才会从内存中删除。

您可以在分配对象时验证是否未复制数据。将对象分配给另一个变量后,可以使用第一个变量更改对象,并在使用另一个变量时更改对象:

function test() {
  var names = ["craig", "silva"];
  globArray = names;
  names[0] = 'peter';
}

现在,当您显示globArray的内容时,您会看到petersilva,因为这两个变量都引用了同一个数组对象。