0

I am still leaning Javascript and I encountered twice a behavior I didn't expect. I would like to understand why it happens and what I should learn to understand it better.

First case: I tried to call a function using a file input filelist as argument. Right after I call my function, I set to null the file input value. In my function, I use a callback that can't get back my fileList since the file input is reseted.

What I don't understand:

I expected the file list object to be somehow "copied" once it was sent to the function. Why changing the original object affects the callback?

Second case: I use a JSON object called values to store, well, values. I iterate on a collection and update a name field of my values object using the iteration index before inserting the values object inside another JSON object. See the code:

var myBaseName = "file"
_.each (myCollection, function(file, i){
    values.name = myBaseName  + " - " + i
    console.log(values.name); //here the name appears correctly, 
                              //i.e. "file - 0", "file - 1"...
    values.size = file.size,
    values.type = file.type,
    allFiles[i]=values; 
});
console.log (allFiles);//here the name appears as the last set, 
                       //i.e. if my collection has 2 objects; 
                       //they both appear as "file - 1"

What I don't understand:

Why is it updating and not simply copied? This is, I expect, the same kind of mechanism than in my first case. I used to code in .net and I never encountered such a behavior. I expected a json object to be some kind of enhanced string.

Community
  • 1
  • 1
Billybobbonnet
  • 3,156
  • 4
  • 23
  • 49
  • 3
    Short and simple - Pass by reference – Nikhil Aggarwal Jul 18 '15 at 15:13
  • 1
    Isn't it pass by sharing? – Kyll Jul 18 '15 at 15:15
  • 1
    JavaScript is pass by value. The issue is that the value of an object is a reference to the object. Assigning a reference does not create a new object. – Pointy Jul 18 '15 at 15:16
  • 1
    [what is the most efficient way to clone an object](http://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-clone-an-object) – Daniel W. Jul 18 '15 at 15:18
  • 1
    What you've encountered is called a Javascript *closure*. The callback function you're using is setting the `name` property to have a *pointer* to the `i` index. Once the callback completes, `i` will have been set to the index of the last element (as it is the last one iterated through), and therefore, the `name` property will contain the index of the last element. See this SO question: https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example – heartyporridge Jul 18 '15 at 15:18
  • Thank you everyone for your help (including answers authors). First case was already solved. Second one has been solved by replacing `allFiles[i]=values; ` with `allFiles[i]=JSON.parse(JSON.stringify(values));`. It works fine now. Tell me if you think it is not the better way to do this. I learned something today :-) – Billybobbonnet Jul 18 '15 at 16:40

2 Answers2

3

I expected the file list object to be somehow "copied" once it was sent to the function. Why changing the original object affects the callback?

Simple answer: it isn't copied. You are mutating an object named values and storing a reference to that object, so each reference points to the same object.

Rein Henrichs
  • 15,437
  • 1
  • 45
  • 55
0

For the first case you must create the copy inside the function.

For the second, use "var values" to specify the scope of this variable to the loop. If you dont, then values will be treated as global.

Fernando Pinheiro
  • 1,796
  • 2
  • 17
  • 21