2

I have an object called Scene and it stores screen dimensions as well as an array of Shape objects, each of which have an x and y coordinate. I would like to scramble a Scene object and get a scrambledScene object so that I can compare the scrambledScene to the original. Here is the function I've come up with:

function scrambleScene(scene) { var scrambledScene = {...scene}; for(var i = 0; i < scene.shapes.length; i++) { scrambledScene.shapes[i].x = getRandInt(0, scene.width); scrambledScene.shapes[i].y = getRandInt(0, scene.height); } return(scrambledScene); } 

The problem is when this function is run, it returns an object that is identical to the Scene object that was passed to it. Nothing was changed. Here are definitions of the functions I used. I am quite new to OOP so feel free to give pointers (unlike JS, why does var clone = object just return a pointer and not another object?!!?!?!!).

function getRandInt(min, max) { return(Math.floor(Math.random() * (max - min + 1)) + 1); } function Shape(shapeX, shapeY, shapeSize, shapeType) { this.x = shapeX; this.y = shapeY; this.size = shapeSize; this.type = shapeType; //circle uses arc() function, which takes the center of the circle as a reference //circle sets the radius to this.size //square uses rect() function, which take the upper left corner as a reference //square sets the height and width of the square to this.size if(this.type !== 'circle' && this.type !== 'square') { console.error('Invalid shapeType: ', this.shapeType); } this.centerX = function() { if(this.type === 'square') { return(this.size/2 - this.x); } if(this.type === 'circle') { return(this.x); } } this.centerY = function() { if(this.type === 'square') { return(this.size/2 - this.y); } if(this.type === 'circle') { return(this.y); } } this.isInside = function(point_x, point_y) { if(this.type === 'square') { //canvas y increases as you go down //if point_x is greater than x + size, then its far too right //if point_x is less than x, then its far too left //if point_y is greater than y + size, then its below //if point_y is less than y, then its above //if none of these are true then its inside if(point_x <= x + size && point_x >= x && point_y <= y + size && point_y >= y) return(true); } if(this.type === 'circle') { //checks distance from point to center of the circle //if its greater than the radius of the circle then its outside //if its less than or equal to the radius then its inside const distance = Math.sqrt(Math.pow(point_x - x, 2) - Math.pow(point_y - y, 2)); if(this.distance >= size) return(true); } } } function Scene(numberOfShapes, sceneWidth, sceneHeight) { this.shapes = []; for(var i = 0; i < numberOfShapes; i++) { var shapeType = Math.random() < 0.5 ? 'square' : 'circle'; this.shapes[i] = new Shape(getRandInt(0, sceneWidth), getRandInt(0, sceneHeight), 100, shapeType) } this.width = sceneWidth; this.height = sceneHeight; } 
4
  • 4
    "it returns an object that is identical to the Scene object that was passed to it. Nothing was changed." - Add a console.log(JSON.stringify(x)) before and after the scrambleScene(x) call and you should see that the shapes in x will have different values after the call - because var scrambledScene = {...scene}; only creates a shallow copy of scene Commented Jan 13, 2021 at 7:42
  • 1
    Imho... Don't use var if your environment supports let and const. There's no good reason for var anymore. Commented Jan 13, 2021 at 7:44
  • @Andreas does shallow copy mean that the Shapes inside scrambledScene are just references to the Shapes inside of the Scene passed to the scrambleScene function and not new objects? Commented Jan 13, 2021 at 7:57
  • Yes. { ...scene } only creates a copy of the scene object itself. The references in scene are copied but not the objects they point at. Commented Jan 13, 2021 at 8:06

1 Answer 1

1

So the Object was being changed, it was just that the clone of that Object was also being changed to be the exact same.

In the scrambleScene function I tried to create is what's called a shallow clone of the Scene object passed. What I really needed was a deep clone. A shallow clone is like if you copied a folder with files inside on Windows, but instead of actually copying the files inside, the files were replaced with shortcuts to those files. If you edit the original file and open the shortcut, you will see the edit because its just a shortcut, not a new file. A deep clone is similar to when you copy a folder with all the files inside. If you edit an original file, its copy won't be changed because they are two different files.

If you continue the analogy, when I ran the scrambleScene function it edited the original file, and when I look at the Shapes, it was the same because it was just a shortcut, not a new file. I needed to copy the file, not create a shortcut.

You can create a completely independent object by using JSON. There are some limitations, but for my case it worked.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.