5

I have a variable myVariable which is continuously changing. At some point I want to capture the value of myVariable (not a reference to myVariable) into another variable myVariableAtSomePoint.

Example code:

var myVariable = 1;

function test () {
    var myVariableAtSomePoint= myVariable;
    console.log(myVariableAtSomePoint);
}

myVariable = 2;

test(); // Prints 2, instead of 1.
Randomblue
  • 112,777
  • 145
  • 353
  • 547
  • Yes, it stores a number (integer). – Randomblue Oct 19 '11 at 14:34
  • 1
    What is it about `myVariableAtSomePoint = myVariable;` that won't work? – Pointy Oct 19 '11 at 14:35
  • @Pointy: That stores the **reference** to `myVariable` (so that `myVariableAtSomePoint` will also change in time). I want `myVariableAtSomePoint` to be static. – Randomblue Oct 19 '11 at 14:36
  • 1
    If you are using jQuery: `var myVariableAtSomePoint = jQuery.extend({}, myVariable);`. If not, copy the source code/idea for `jQuery.extend` from jQuery :P – Esailija Oct 19 '11 at 14:37
  • 1
    Well you said it's just "a number (integer)". – Pointy Oct 19 '11 at 14:51
  • @pointy I think he said it's an object that stores a number(ex: `{n:3}` but I am confused as well :D – Esailija Oct 19 '11 at 14:55
  • @Pointy: I've added example code to clarify – Randomblue Oct 19 '11 at 14:55
  • @Esailija: I've added example code to clarify – Randomblue Oct 19 '11 at 14:56
  • OK, well if it really is just a number, then your understanding of what that assignment statement does is incorrect. That simple assignment copies the value of the number (like, 3 or 2021 or whatever) to the other variable, and subsequent changes to "myVariable" will absolutely not affect "myVariableAtSomePoint". – Pointy Oct 19 '11 at 15:06
  • If you'd like to think about it as "copying a reference", alternatively, then think of numbers as immutable objects. The only way to make "myVariable" take on a different numeric value is to make it reference a different number object. Again, such a change will not affect "myVariableAtSomePoint". – Pointy Oct 19 '11 at 15:07
  • 2
    The problem you are having is not about references. You are calling `test` **after** you changed value. The code inside the test function is not executed until you call the function. – Felix Kling Oct 19 '11 at 15:15

5 Answers5

4

You mention in your comments that myVariable is a number. Since myVariable houses a primitive type, simply use the code below:

myVariableAtSomePoint = myVariable;

Take a look at JAVASCRIPT: PASSING BY VALUE OR BY REFERENCE. Here's a quote:

When passing in a primitive type variable like a string or a number, the value is passed in by value.

I would also suggest reading: How do I correctly clone a JavaScript object?

EDIT:

I believe that you're assuming that the placement of the function in the code affects the value of the variables. It does not. See examples below:

This:

function test () {
    var myVariableAtSomePoint= myVariable;
    console.log(myVariableAtSomePoint);
}

myVariable = 2;

test(); // Prints 2, instead of 1.

Is the same as this:

var myVariable = 1;

function test () {
    var myVariableAtSomePoint= myVariable;
    console.log(myVariableAtSomePoint);
}

myVariable = 2;

test(); // Prints 2, instead of 1.

Your problem is that you're changing the value of myVariable before you're assigning it to myVariableAtSomePoint. For this to work as you want, you'll need to call the test() function before you change the value of myVariable

var myVariable = 1;

function test () {
    var myVariableAtSomePoint= myVariable;
    console.log(myVariableAtSomePoint);
}

test(); // Prints 1
myVariable = 2;
test(); // Prints 2

IMPORTANT: No matter the placement of the function, the code inside test() is not executed until you call the function.

Community
  • 1
  • 1
James Hill
  • 60,353
  • 20
  • 145
  • 161
  • That blog post sadly embraces a very common misunderstanding of the terms "pass by reference" and "pass by value". Those have a very specific meaning when talking about programming languages. In that sense, JavaScript (like Java, and *unlike* C++) is strictly and only pass-by-value. – Pointy Oct 19 '11 at 14:53
  • @Pointy, the reason that reassigning a parameter inside a function doesn't change the original passed variable is that the function creates it's own local variables and copies the parameter references (or values if they are primitive) to these created variables. Now, if you pass in an object and modify it inside the function, the original object will be modified as well because the copied variable inside the function points to the same object as the original variable. Given this, is it still strictly pass-by-value, even if the original passed in variables can be modified inside the function? – Esailija Oct 19 '11 at 15:26
  • @Esailija Yes, it is strictly pass-by-value. The simple test to determine that is to ask this: can you write a `swap(a, b)` function like you can in C++ with reference parameters ("&p")? In JavaScript (and Java), you cannot. Yes, you can manipulate the properties of objects passed, and yes, that means you've been passed a reference to an object, but that's just not what "pass by reference" means. It's a very precise term. – Pointy Oct 19 '11 at 15:49
  • @Pointy, thanks for the clarification :) My head is still spinning from "that means you have passed a reference [to an object], but it's not what pass by reference means" though :D – Esailija Oct 19 '11 at 16:11
  • I know, and I don't mean to be picky or to "split hairs". It would be a lot easier if the term "pass by reference" were something like "robo-mecha parameters" because it would be less likely to cause confusion. It's a concept that dates way way back to very early work in programming language design. (Algol 60 had some really crazy parameter passing semantics.) – Pointy Oct 19 '11 at 16:18
  • @Pointy, I was -24 when Algo 60 was released :-O – James Hill Oct 19 '11 at 16:26
  • `test(); // Prints 1 myVariable = 2; test(); // Prints 1` Maybe I didn't read the whole answer in the correct context but shouldn't it still print 1 and then 2 in the respective calls to test() ? – codisfy Jul 04 '15 at 10:19
3

The variable only holds the reference and nothing else. If you want a copy of the object that the variable is pointing to, you will need some way to copy that object. Either you can implement a copy method on the object itself (if you know what properties it has) or you can iterate through all properties on the object using a for ... in loop and copy them to a newly allocated object. Something like:

//o is the object you want to copy
var o2 = {}; //gives a new object
for (x in o) {
   o2[x] = o[x];
}
Mathias Schwarz
  • 7,099
  • 23
  • 28
  • modifying any o2[x] objects will also modify the original myVariable[x] objects though. – Esailija Oct 19 '11 at 14:42
  • Don't forget to check `o.hasOwnProperty(x)` to prevent the functions of `o` from being copied over as well. – zzzzBov Oct 19 '11 at 14:44
  • @Esailija: sure, but the OP is not very specific about what he wants. My code will give a shallow copy of `o`. A deep copy of `o` can be obtained by using the same technique recursively on the values of `o[x]`. – Mathias Schwarz Oct 19 '11 at 14:45
  • @zzzzBov: In general, one would have to do a few more things to make it behave correctly in combination with a prototype hierachy. – Mathias Schwarz Oct 19 '11 at 14:47
1

Your code:

var myVariable = 1;

function test () {
    var myVariableAtSomePoint= myVariable;
    console.log(myVariableAtSomePoint);
}

myVariable = 2;

test(); // Prints 2, instead of 1.

You assign 2 to myVariable, and then assign myVariable (which has now value of 2) to myVariableAtSomePoint via test() so of course it is 2. You don't need any magic copying here (since numbers are primitive) just assigment is enough.

Esailija
  • 138,174
  • 23
  • 272
  • 326
0

You can do something this to do exactly what you wanted. It is slightly more involved however.

var myVariable = 1;

var test = null;
(function() {
  const myVariableAtSomePoint = myVariable;
  test = function() {
    console.log(myVariableAtSomePoint);
  }
})();

myVariable = 2;

test(); // Prints 1
Chase
  • 1,419
  • 12
  • 17
0

You'll just need to copy each property on the object, of course if there are sub-objects they might get passed by reference as well:

function copy(o) { //could be called "clone"
  var i, n;
  n = {};
  for (i in o)
  {
    if (o.hasOwnProperty(i)) {
      n[i] = o[i];
    }
  }
  return n;
}
zzzzBov
  • 174,988
  • 54
  • 320
  • 367