-1

I wanted to encapsulate the position of a sprite within another object. So that instead of using tile.x and tile.y I would access via tile.position.x and tile.position.y.

Yet once I set the value of tile.position within the init-method all the instances of the tile-object change to the same value. Why is that?

As when I set tile.x everything works as expected, meaning each object gets the right value.

This is how I create the multiple instances:

In a for loop I am creating multiple instances of said object:

for (var y = 0; y < 10; ++y) {
  for (var x = 0; x < 10; ++x) {
    var tile = Object.create(tileProperty);
    tile.init(x, y);
    ...
  }
}

And this is the cloned object:

var tileProperty = {
    // this works
    x: null, 
    y: null,
    // this will get changed for ALL instances
    position: { 
        x: null,
        y: null
    },
    init: function(x, y) {
        this.name = x.toString() + y.toString();
        this.x = x;
        this.y = y;
        this.position.x = x;
        this.position.y = y;
        this.canvas = document.createElement('canvas');
        var that = this;
        $(this.canvas).bind('click', function() {
            console.log(that.position, that.x, that.y);
        });

        document.body.appendChild(this.canvas);
    }
}
k0pernikus
  • 60,309
  • 67
  • 216
  • 347
  • 1
    duplicate of [Crockford's Prototypal inheritance - Issues with nested objects](http://stackoverflow.com/questions/10131052/crockfords-prototypal-inheritance-issues-with-nested-objects). See also [Why are my JS object properties being overwritten by other instances](http://stackoverflow.com/q/13127589/1048572) – Bergi Dec 11 '12 at 14:53
  • Possible duplicate of [Why are my JavaScript object properties being overwritten by other instances?](https://stackoverflow.com/questions/13127589/why-are-my-javascript-object-properties-being-overwritten-by-other-instances) – Heretic Monkey Jan 31 '19 at 16:52

2 Answers2

1

You're having a reference to the same position object in all your objects.

What you should do is using the standard prototype solution :

function tileProperty() {
    this.position = { 
        x: null,
        y: null
    };
}
tileProperty.prototype.init = function(x, y) {
    this.name = x.toString() + y.toString();
    this.x = x;
    this.y = y;
    this.position.x = x;
    this.position.y = y;
    this.canvas = document.createElement('canvas');
    var that = this;
    $(this.canvas).bind('click', function() {
        console.log(that.position, that.x, that.y);
    });

    document.body.appendChild(this.canvas);
}

and then build your instance using

var tp = new tileProperty();
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • If you are using a constructor (should be capitalized, btw), you would not use a `init` method – Bergi Dec 11 '12 at 14:56
1

Use this:

var tileProperty = {
    position: { // we will inherit from this
        x: null,
        y: null,
        init: function(x, y) {
            this.x = x;
            this.y = y;
        }
    },
    init: function(x, y) {
        this.name = x.toString() + y.toString();
        // create an own Position object for each instance
        this.position = Object.create(this.position);
        // and initialize it
        this.position.init(x, y); // you might inline this invocation of course
        …
    },
    …
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375