How do I keep a function working with local variables from changing the value of a global? It's like I've passed the value by reference without meaning to do so.
https://github.com/upstageleft/Weird-javascript-problem
Global variable keeps changing when source data (value of an element from a matrix array in a closure) is copied to a local variable and then the local variable value is modified.
Cannot wrap my head around what is going on, but problem renders consistently in FF, Safari and Chrome.
Link includes code and dynamic display of variable values with button to repeat. Should be enough, but you can always view source to verify.
EXAMPLE DATA:
In the lists below, the first item reflects the value of a global variable populated by a value copied from a matrix array in a closure by means of a helper function.
The second list shows that the global value has changed when it should not have. The value of the specified cell of the matrix has been copied to a new variable, and that variable has been manipulated, but the result of that manipulation is somehow copied back to both the global variable and the matrix variable!
- globVal initial value: 1,1 ←(should be constant)
- globVar's scope: [object Window]
- myObj: { oSrc: "1,1", oX: 2 }
Before:
- globVal[0] (global): 1
- Operation: newVal = myVal[0] * myObj.oX
- myVal[0] (local): 1
- newVal (local): 2
- map.see(1,1) (closure): 1,1
After:
- globVal[0] (global): 2
- Operation: myVal[0] = newVal
- myVal[0] (local): 2
- newVal (local): 2
- map.see(1,1) (closure): 2,1
Here is the code performing the operations, along with a helper function to pull values from the matrix and the object containing the data value to be applied in the operations.
CODE BLOCK A
1 | function doStuff(){
2 | var myVal = mxGet( myObj.oSrc );
3 | var newVal = myVal[0] * myObj.oX;
4 | myVal[0] = newVal; // weirdness happens here!
5 | }
6 |
7 | function mxGet( xy ){
8 | var x_y = xy.split(',');
9 | return map.see( x_y[0], x_y[1] );
10 | }
11 |
12 | myObj = {
13 | oSrc: '1,1',
14 | oX: 2
15 | }
Here are the onload function which initializes the global and the closure which stores the matrix.
CODE BLOCK B
1 | function init(){
2 | globVal = mxGet('1,1'); // global declared here
3 | that = this;
4 | doStuff();
5 | }
6 |
7 | map = (function(){
8 | myHiddenMatrix = [ [ [0,0], [0,1], [0,2] ],
9 | [ [1,0], [1,1], [1,2] ],
10 | [ [2,0], [2,1], [2,2] ] ];
11 | return {
12 | pin: function( x, y, val ){ myHiddenMatrix[ x ][ y ] = val; },
13 | see: function( x, y ){ return myHiddenMatrix[ x ][ y ]; }
14 | }
15 | })();