简体   繁体   中英

JavaScript: assignment to an object within an array changes the value of all objects in the array

I have an object which have an array to hold all the children of this object, the children are also instances of the same object (I need this for a tree like structure where the object is a node of the tree)

var bugObject = function(kFlag){
  this._kFlag = kFlag; 
  this._children = []
}

bugObject.prototype.getKFlag = function(){
  return this._kFlag; 
}; 


bugObject.prototype.setChildrenFromData = function(data){

 var i = 0;
 var kFlag = {flagType : 'someFlag', flagValue : -1};
 kddFlag.flagType = data.flagType;

 var len = data.flagValues.length; 
 for( i = 0 ; i < len ; i++){
        kFlag.flagValue = data.flagValues[i];
        this._children.push(
            new bugObject(kFlag)
        );

                 //this is just to print the children 
        for(j = 0; j<=i; j++){
            console.log('child : ' + j + ' for test :' + i); 
            console.log(this._children[i].getKFlag());
        }
        console.log('--------------------');
 }

}; 

The idea is to create the children of this object based on some data using the setChildrenFromData method here is how I am doing this:

function main(){

console.log('main is called'); 
var data = {"flagType":"someFlag","flagValues":[0,0,0,0,0,0,0,0,1,0,0]}; 

var rootNode = new bugObject(null); 
rootNode.setChildrenFromData(data); 

}

main(); 

The problem is that instead of getting 11 objects each of them have one of these flags [0,0,0,0,0,0,0,0,0,0,1] I get 11 objects all of them have the flag 1, (the last one)!

Could you please see what is wrong!

Thanks

The problem is this:

for( i = 0 ; i < len ; i++){
        kddFlag.flagValue = data.flagValues[i];
        this._children.push(
            new bugObject(kddFlag)
        );

you're creating 11 bugObject . But all of them have this._kddFlag pointing to the same kddFlag object, at the end of the loop kddFlag.flagValue is 1. To fix this, move your code into the loop. Like this:

for( i = 0 ; i < len ; i++){
           var kddFlag = {flagType : 'outlier', flagValue : -1};
            kddFlag.flagType = data.flagType;
            kddFlag.flagValue = data.flagValues[i];
            this._children.push(
               new bugObject(kddFlag)
            );

This is a problem with assigning references to objects, and is well known, and even happens in other languages.

I'll give you a simpler example:

Let's say you want a 3x3 matrix, modelled as an array of arrays, filled with rows that are all zeros.

You might be tempted to write.

row = [0,0,0];
A = [];
for(j=0;j<3;++j) A[j] = row;

But then if you change A[0][0] = 10;

And you look in A[1][0] , you get 10 , not 0 .

This is because there is only one row , and all of the elements of A are assigned to it.

To correct this pattern in Javascript, the object needs to be a new object each time. This can be done with a literal A[j]=[0,0,0] or it can be A[j]=row.slice() which makes a shallow copy that solves the problem for one level, or a deep copy.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM