JavaScript variables reference

5

To generate the following array:

1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5

Consider the following code for constructing an array with equal rows:

var linha = [1, 2, 3, 4];
var matriz = [linha, linha, linha ];
matriz[3] = linha ;      // outra alternativa
matriz.push(linha);      // mais outro modo

It seems logical to use this code to generate the array. But we have one though, we're adding elements by reference in Array matriz .

If we try

matriz[0].push();       // retirar o elemento na posição A[0][4]
matriz[1][1] = 10;      // alterarmos A[1][1] de 2 para 10

We replicate the changes to all rows.

I would like you to tell me about this JavaScript behavior:

  • Problems that careless use may involve, and
  • What is the simplest and most acceptable way to create this array and make those changes to it.
asked by anonymous 21.11.2014 / 03:47

1 answer

5

If you want to change values independently, you need something like this:

var linha = [1, 2, 3, 4, 5];
var matriz = [];

for( var i = 0; i<5; i++ ) {
   matriz.push( linha.slice() );
}

//testando alteração:
matriz[2][2] = 999;

for( var i = 0; i<5; i++ ) {
  body_log( 'matriz[' + i + ']:' + matriz[i] );
}


// só pra nao precisar de console:
function body_log(msg) {
  document.body.innerHTML = document.body.innerHTML + '<p>' + msg + '</p>';
}

What is happening here is that .slice() is one of the ways to produce a clone of an array , not a new reference.

As you mentioned yourself, when someone does umaVariavel = umArray in JS, you are simply saying that umaVariavel points to the same memory space as umArray , and the consequence is that when you access either of two things, is seeing the same data. Any changes made, either by a name or another, will be reflected when you access them.

The same thing happens when you point an array sub-index to another array. That sub-index will be pointing to the same space as the original variable.


Behavior in recursion

The following example is to confuse some and worry others. Try to endorse what happens when you use arrays as a reference, reference within array :

var matriz = [];
matriz.push( [00, 01, 02,     03, 04, 05] );
matriz.push( [10, 11, 12,     13, 14, 15] );
matriz.push( [20, 21, 22,     23, 24, 25] );
matriz.push( [30, 31, 32, matriz, 34, 35] );
matriz.push( [40, 41, 42,     43, 44, 45] );
matriz.push( [50, 51, 52,     53, 54, 55] );

body_log( 'matriz[1][1]      <br>' + matriz[1][1] );
body_log( 'matriz[2][2]      <br>' + matriz[2][2] );
body_log( 'matriz[3][3]      <br>' + matriz[3][3] );
body_log( 'matriz[3][3][2]   <br>' + matriz[3][3][2] );
body_log( 'matriz[3][3][1][2]<br>' + matriz[3][3][1][2] );

// alterando:
matriz[3][3][1][2] = 999;
body_log( 'matriz[3][3][1][2] = 999<br>');
body_log( 'resultado:<br>' + matriz );

matriz[0][0] = matriz[3];
matriz[3][3][0][0][3][4] = "que?";

body_log( 'matriz[0][0] = matriz[3] e matriz[3][3][0][0][3][4] = "que?"' );
body_log( 'resultado:<br>' + matriz );

function body_log(msg) { document.body.innerHTML = document.body.innerHTML + '<p>' + msg + '</p>'; }

Notice how array can access itself through one of its members? I hope you're seeing this example in a well-implemented browser , which simply hides the 3.3 member from array , otherwise it will collapse.

Note that when we change the member [3] [3] [1] [2] from the array we are actually changing member [1] [2], since member [3] [3] is itself array .

To make it worse, I added in the demonstration a change by transforming the item [0] [0] into line 3 of the array, and changing one of its members, and changing the entire line 4 to a string, by means of three recursions . For those who like to play Portal , it's easy to understand.

Imagine in a real case the kind of confusion you can make when you do not know the difference between a true value and a mere reference.

    
21.11.2014 / 04:26