2

Looking at the following code, can someone explain how values are passed around in 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';
      }
  }
}

Then in another functions:

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;
}

I cut out some code for simplicity sake but its still quite convoluted. Basically there are 2 objects (images & blocks) which are nested key:value pairs. In the first block of code

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

In the second line of code there is

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

There is no .img in "images" before the first block of code where .img is added to "theme". But this seems to be reflected back into "images" as seen in the second block of code. Are all objects like pointers in JavaScript? Will "result" have the same relationship with "blocks" as "theme" has with "images"? What if I remove an element from "theme", will that be reflected in "images"?

Nate
  • 919
  • 2
  • 9
  • 18
  • If it was written as `i = new Image(); i.img.src = 'images/'+theme[tsec].src+'.png'; theme[tsec] = i;` would it make more sense to you? – Conrad Frix May 17 '12 at 17:39

4 Answers4

4

Using theme = images[sec] you will indeed create a pointer to that object in memory. So adding img to theme object will as well add img to that image, as they are the same object. So yes, the same goes for result.
Altering, adding or removing properties of an object referenced in such a way will influence the actual object. The same goes for arrays.

If you don't like that behavior, you should clone the object. You can clone a simple object simply by copying all properties:

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

But if any property of that original is an array or object itself, it will be a reference. If you don't have any objects or arrays as properties, the above snippet will do fine. Otherwise you should write a clone function and recursively clone every member of the original.

soimon
  • 2,400
  • 1
  • 15
  • 16
2

Are all objects like pointers in JavaScript?

Effectively, yes, though I believe it would be more generally stated that in JavaScript an Object is a "reference type".

If var a references an object, and a is assigned to var b, b will get a copy of the reference that a holds, so a and b will both reference the same object data in memory.

Changes made from the a reference are observable from the b reference.

Note that this is still a "by value" assignment, but the value copied is the value of the reference, not the object itself.

cliffs of insanity
  • 3,683
  • 1
  • 16
  • 18
1

The reason you are experiencing this is that objects are passed by reference. There are ways to clone objects. Take a look at this other SO post How do I correctly clone a JavaScript object?

Community
  • 1
  • 1
marteljn
  • 6,446
  • 3
  • 30
  • 43
1

You're altering images[sec][tsec] in both cases, which refers to the very same object in memory. Just doing theme = images[sec] does not make a copy of the object.

A more trivial example of this behaviour is this:

var obj = {};
var obj2 = obj;

obj.a = 123;
obj2.a; // 123
pimvdb
  • 151,816
  • 78
  • 307
  • 352