Initializing a class in a loop in javascript uses the last value

First of all, I know that there are many closing questions in JavaScript, especially when it comes to loops. I read many of them, but I just can't figure out how to fix my own problem. My main experience is C #, C ++, and some ASMs, and it gets a little used to JavaScript.

I am trying to populate a 3-dimensional array with new instances of the class (called Tile) in some for loops. All I want to do is pass a reference to some other class (called Group) that is created in the first loop (and also added to another array). As you might have guessed, after the cycles are completed, each instance of the Tile class has a reference to the same Group object, namely the last one to be created.

Apparently, instead of passing a reference to the Group object, a reference is passed to some variable local to the function, which is updated at each iteration of the loop. My assumption is that the solution to this problem has something to do with closure, as it seems to be related to many of the similar problems that I encountered in finding a solution.

I posted some abbreviated code that reveals the essence of the problem on jsFiddle :

//GW2 namespace (function( GW2, $, undefined ) { //GW2Tile class GW2.Tile = function(globalSettings, kineticGroup) { //Private vars var tilegroup = kineticGroup; // console.log(tilegroup.grrr); //Shows the correct value var settings = globalSettings; this.Test = function(){ console.log(tilegroup.grrr); } this.Test2 = function(group){ console.log(group.grrr); } } //Class }( window.GW2 = window.GW2 || {}, jQuery )); var zoomGroups = []; var tiles = []; var settings = {}; InitArrays(); tiles[0,0,0].Test(); //What I want to work, should give 0 tiles[0,0,0].Test2(zoomGroups[0]); //How I'd work around the issue function InitArrays(){ var i, j, k, zoomMultiplier, tile; for(i = 0; i <= 2; i++){ zoomGroups[i] = {}; zoomGroups[i].grrr = i; tiles[i] = []; zoomMultiplier = Math.pow(2, i); for(j = 0; j < zoomMultiplier; j++){ tiles[i,j] = []; for(k = 0; k < zoomMultiplier; k++){ tile = new GW2.Tile(settings, zoomGroups[i]); tiles[i,j,k] = tile; } } } } 

Until now, when working with JavaScript, I usually twisted the code a bit to make it work, but I was tired of using workarounds that seem messy, since I know that there really needs to be a fairly simple solution, I just don't like asking for help, but it really makes my head. Any help is greatly appreciated.

+4
source share
1 answer

Multidimensional Arrays

Problem

The first problem with your code above is how you are trying to create multidimensional arrays.

The syntax you use is:

 tiles[0,0,0] 

However, the way to interpret JavaScript will be as follows:

 tiles[0] 

Access to multidimensional array

If you want to access the multicast array, you should use:

 tiles[0][0][0] 

And to create a multidim array you will need to do the following:

 tiles = []; tiles[0] = []; tiles[0][0] = []; tiles[0][0][0] = 'value'; 

or

 tiles = [[['value']]]; 


As for your code

In your code you should use:

 tiles[i][j][k] = tile; 

But you must also make sure that each additional array exists up to its value, otherwise you will get undefined or illegal offset errors.

You can do this by:

 (typeof tiles[i] === 'undefined') && (tiles[i] = []); (typeof tiles[i][j] === 'undefined') && (tiles[i][j] = []); tiles[i][j][k] = tile; 

Obviously, the above can be optimized depending on how you go through your loops, that is, it is best to make sure that the level of tiles[i] exists as an array before entering the loop [j] , and then don't worry about checking it existence back during step j .


Other options

Depending on your data set, or at least what you hope to do with the tiles array, consider using an object:

 /// set up tiles = {}; /// assignment tiles[i+','+j+','+k] = 'value'; 

However, this method is likely to be slower, although I was mistaken several times according to my assumptions and various JavaScript interpreters. This would probably be jsPerf to be your friend.


Optimization

One of the benefits of using the tiles[i][j][k] approach is that it allows you to optimize your links. For example, if you are going to process several actions at one level of your multidimensional array, you should do the following:

 /// set up var ij = tiles[i][j]; /// use in loops or elsewhere ij[k] = 'value' 

This is only useful if you have accessed the same level more than once.

+2
source

Source: https://habr.com/ru/post/1489470/


All Articles