3

I created a 2D array that contains an object, and each object has two variables.

When I printed out those objects, I found that every object has the same value.

If I change one of the objects, other objects will change too.

class test{
    constructor(x, y){
        self.x = x;
        self.y = y;
    }
    print(){
        console.log(self.x, self.y);
    }
}

arr = new Array(3);

for(let i=0;i<3;i++){
    arr[i] = new Array(3);
}

for(let i=0;i<3;i++){
    for(let j=0;j<3;j++){
        arr[i][j] = new test(i, j);
    }
}

for(let i=0;i<3;i++){
    for(let j=0;j<3;j++){
        arr[i][j].print();
    }
}

It just prints nine 2 2. I have no idea what's going on.

Even if I tried:

arr[1][2] = new test(2, 3);

It prints nine 2 3.

I will be appreciated if anyone helps me.

:P

VLAZ
  • 18,437
  • 8
  • 35
  • 54
Ben_TW
  • 115
  • 6
  • 7
    I'm pretty sure you want `self.x` to be `this.x`, etc. unless this is really a Python question. – Mark Mar 27 '19 at 12:41

4 Answers4

10

JavaScript is not Python, use this, and it will work.

class test{
    constructor(x, y){
        this.x = x;
        this.y = y;
    }
    print(){
        console.log(this.x, this.y);
    }
}

arr = new Array(3);

for(let i=0;i<3;i++){
    arr[i] = new Array(3);
}

for(let i=0;i<3;i++){
    for(let j=0;j<3;j++){
        arr[i][j] = new test(i, j);
    }
}

for(let i=0;i<3;i++){
    for(let j=0;j<3;j++){
        arr[i][j].print();
    }
}

(You luckily/unluckily ended up using Window.self, everywhere)

tevemadar
  • 9,697
  • 2
  • 15
  • 36
  • 2
    @Teemu, thanks. It disturbed me a little, since it should have been complaining about accessing a field of `undefined`. – tevemadar Mar 27 '19 at 12:48
5

The assignment of x and y to self in the constructor is your problem, change self to this to point to the current instance of the class object.

class test{
    constructor(x, y){
        this.x = x;
        this.y = y;
    }
    print(){
        console.log(this.x, this.y);
    }
}

arr = new Array(3);

for(let i=0;i<3;i++){
    arr[i] = new Array(3);
}

for(let i=0;i<3;i++){
    for(let j=0;j<3;j++){
        arr[i][j] = new test(i, j);
    }
}

for(let i=0;i<3;i++){
    for(let j=0;j<3;j++){
        arr[i][j].print();
    }
}

From the MDN docs:

The Window.self read-only property returns the window itself, as a WindowProxy. It can be used with dot notation on a window object (that is, window.self) or standalone (self)

So in your case when you assigned x and y to self.x and self.y two new properties of the self was created and you kept overwriting them in your loop which resulted in the last value (2,2) of the iteration being assigned to the x and y property of self

Fullstack Guy
  • 14,425
  • 3
  • 18
  • 35
4

The variable self you use is actually the window object, so self.x = x just attaches an x property to window and sets the value. When you call console.log(self.x, self.y); this gets the x and y properties from window and since there is only a single instance of that, you get the last assigned values.

class test{
    constructor(x, y){
        self.x = x;
        self.y = y;
    }
    print(){
        console.log(self.x, self.y);
    }
}

new test(4, 2);

console.log(window.x);
console.log(window.y);

You want to use this to refer to the current object instance

class test{
    constructor(x, y){
        this.x = x;
        this.y = y;
    }
    print(){
        console.log(this.x, this.y);
    }
}

arr = new Array(3);

for(let i=0;i<3;i++){
    arr[i] = new Array(3);
}

for(let i=0;i<3;i++){
    for(let j=0;j<3;j++){
        arr[i][j] = new test(i, j);
    }
}

for(let i=0;i<3;i++){
    for(let j=0;j<3;j++){
        arr[i][j].print();
    }
}
VLAZ
  • 18,437
  • 8
  • 35
  • 54
2

The self doesnot refer to the instance of class. self in another name for window. See the snippet what is self

According to MDN

The Window.self read-only property returns the window itself

class test{
    constructor(x, y){
        console.log(self === window) //true
        console.log(self) //widnow object       
    }
}
let x = new test(1,2);

So every time you create a new instance of test self.x and self.y is change. self.y and self.x is same a window.x and window.y

Using this in place of self will solve the problem.

class test{
    constructor(x, y){
        this.x = x;
        this.y = y;
    }
    print(){
        console.log(this.x, this.y);
    }
}

arr = new Array(3);

for(let i=0;i<3;i++){
    arr[i] = new Array(3);
}

for(let i=0;i<3;i++){
    for(let j=0;j<3;j++){
        arr[i][j] = new test(i, j);
    }
}

for(let i=0;i<3;i++){
    for(let j=0;j<3;j++){
        arr[i][j].print();
    }
}
Maheer Ali
  • 32,967
  • 5
  • 31
  • 51