2

看看下面的代码,有人能解释一下值是如何在 JavaScript 中传递的吗?

function loadImages() {
  for(var sec in images) {
    theme = images[sec];
      for(var tsec in theme) {
        theme[tsec].img = new Image();
        theme[tsec].img.src = 'images/'+theme[tsec].src+'.png';
      }
  }
}

然后在另一个函数中:

function definitionToSpriteDataMapping() {
  var result = {};
  for(var definition in blocks) {
    var sprite = blocks[definition].sprite;
    for(var secnm in images) {
      section = images[secnm];
      for(var spritenm in section) {
        if(sprite == spritenm) {
          result[definition] = {};
          result[definition].img = section.img;
        }
      }
    }
  }
  return result;
}

为了简单起见,我删掉了一些代码,但它仍然很复杂。基本上有 2 个对象(图像和块)是嵌套的键:值对。在第一块代码中

theme = images[sec]; 
theme[tsec].img.src = 'images/'+theme[tsec].src+'.png';

在第二行代码中有

section = images[secnm];
result[definition] = {};
result[definition].img = section.img;

在将 .img 添加到“主题”的第一个代码块之前,“图像”中没有 .img。但这似乎反映在第二个代码块中的“图像”中。所有对象都像 JavaScript 中的指针吗?“结果”与“块”的关系是否与“主题”与“图像”的关系相同?如果我从“主题”中删除一个元素,那会反映在“图像”中吗?

4

4 回答 4

4

使用theme = images[sec]你确实会在内存中创建一个指向该对象的指针。因此,添加imgtheme对象也将添加img到该图像,因为它们是同一个对象。所以是的,同样适用于result.
更改、添加或删除以这种方式引用的对象的属性将影响实际对象。数组也是如此。

如果您不喜欢这种行为,则应该克隆该对象。您可以通过复制所有属性来克隆一个简单的对象:

var original = { name: "James", age: 73, male: true };
var clone = { };
for( var k in original )
    clone[ k ] = original[ k ];

但是,如果它的任何属性original是数组或对象本身,它将是一个引用。如果您没有任何对象或数组作为属性,那么上面的代码片段就可以了。否则,您应该编写一个克隆函数并递归地克隆原始的每个成员。

于 2012-05-17T17:44:56.640 回答
2

所有对象都像 JavaScript 中的指针吗?

实际上,是的,尽管我相信更普遍的说法是,在 JavaScript 中,对象是一种“引用类型”。

如果var a引用一个对象,并a分配给var bb将获得一个引用的副本a,因此ab都将引用内存中的相同对象数据。

从参考中做出的更改可以从a参考中观察到b

请注意,这仍然是“按值”赋值,但复制的值是引用的值,而不是对象本身。

于 2012-05-17T17:37:00.330 回答
1

您遇到这种情况的原因是对象是通过引用传递的。有很多方法可以克隆对象。看看其他 SO 帖子如何正确克隆 JavaScript 对象?

于 2012-05-17T17:39:13.020 回答
1

images[sec][tsec]在这两种情况下都在改变,它指的是内存中的同一个对象。只是做theme = images[sec]不会复制对象。

这种行为的一个更简单的例子是:

var obj = {};
var obj2 = obj;

obj.a = 123;
obj2.a; // 123
于 2012-05-17T17:40:02.753 回答