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

1
  • 7
    I'm pretty sure you want self.x to be this.x, etc. unless this is really a Python question. Commented Mar 27, 2019 at 12:41

4 Answers 4

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)

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

1 Comment

@Teemu, thanks. It disturbed me a little, since it should have been complaining about accessing a field of undefined.
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

Comments

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();
    }
}

3 Comments

OMG I didn't notice that.
Thank you so much.
@Ben_TW it's alright, we all make mistakes. And learn from them. The reason I know about self is because I've made a mistake very similar to yours in the past. It also took me a while to solve :P
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();
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.