Shibasis Sengupta
Shibasis Sengupta

Reputation: 649

javascript Slice is not doing shallow copy

I wrote this following JS program to solve the N-queen problem and it works fine. But then I was trying to modify the output with a particular format. Then I observed a strange issue.

If you look at the below code, in the function, 'findSolution' I am passing an array - 'board'. Then I am taking a copy of this array in this line -

let boardCp=board.slice(); //Board is an array of arrays (idea is to never modify the original board object) 

This copy is then passed to another function for modification. When that function modifies this copy, the original array ('board' in this case) should remain unchanged - right? But surprisingly I see that the original array is also being modified.

Can someone please help me understand why is this happening? Please let me know if I need to give further details.

	var solveNQueens=function(A)
	{
		var retArr=[];
		
		var board=[];
		for(var i=0;i<A;i++)
		{
			var row=[];
			for(var j=0;j<A;j++)
			{row.push('.');}
		board.push(row);
		}				
		
		findSolution(board.slice(),A,0,{},retArr);	
		return retArr;
	}

	var findSolution=function(board,boardSize,rowNum,queenpositions,retArr)
	{		
		for(var j=0;j<boardSize;j++)
		{
			if(rowNum==0)
				queenpositions={};

			if(isSafeToPlace(rowNum,j,queenpositions))
				{		
				var foundSolutionsToOtherQueens=true;
				queenpositions[rowNum]=j;   
				var nextRowNum=rowNum+1;
				if(nextRowNum<boardSize)
				foundSolutionsToOtherQueens=findSolution(board,boardSize,nextRowNum,Object.assign({},queenpositions),retArr);
			    else
				{
				  debugger;
				  let boardCp=board.slice();
			      retArr.push(convertQueenPositionToArray(boardCp,queenpositions));				  
				  }
		
				if(!foundSolutionsToOtherQueens)
					delete queenpositions[rowNum];
				
			}
	     }		 
		 return false;
	}
	
	var convertQueenPositionToArray=function(boardCp,queenpositions)
	{
		for(var i=0;i<boardCp.length;i++)
		{			
			var row=boardCp[i];
			for(var j=0;j<row.length;j++)
			{
			if(queenpositions.hasOwnProperty(i) && j==queenpositions[i])	
				row[j]='Q';
			}
		}
		return boardCp;
	}
	
	var isSafeToPlace=function(rowNum,j,existingQueenpositions)
	{
		for(var prop in existingQueenpositions)
		{
			var colmn=existingQueenpositions[prop];			
			if(colmn===j || colmn==(j-(rowNum-prop)) || colmn==(j+(rowNum-prop)))
				return false;			
		}
		return true;
	}

Upvotes: 1

Views: 1061

Answers (1)

FisNaN
FisNaN

Reputation: 2875

slice method DOES NOT make deep copy.

It only copies the first layer of the array (sting and number only).

Let's consider the example below:

const nestedArray = [
  1,
  [2, 3],
  { y1: 4, y2: 5},
];

const cloneArray = nestedArray.slice();

// this is safe
cloneArray[0] = 'new value 1';
console.log(nestedArray[0]); // expect 1

// cloneArray[1] is a pointer to the original array
cloneArray[1][0] = 'new value 2';
console.log(nestedArray[1]); // expect 2, got 'new value 2'

// cloneArray[2] s a pointer to the original object
cloneArray[2].y1 = 'new value 4';
console.log(nestedArray[2]); // expect { y1: 4, y2: 5}, got { y1: 'new value 4', y2: 5}

  • If you need a deep copy for nested array or object, you have to do it recursively or use a third part library, such as lodash: var cloneArray = _.cloneDeep(nestedArray)

  • Another shortcut solution is to do JSON.parse(JSON.stingify(nestedArray))

Upvotes: 3

Related Questions