Why won't this Javascript Object Change?

Viewed 60

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;
}
1 Answers

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.

Related