0

Hi Im trying to get my head around javascript oop and am running into a problem,I'm building a constructor class, in the class I define the properties now i want to define some methods that alter those properties, but when I instanciate the object and invoke the method the the consol tells me that the properties are undefined. I imagine that this might have something to do with scope, I`ve been looking around google alot but all introductory articles are basically the same.

heres a simplifed version of the code. In my example code I want a shape to move around on the canvas. the object it self will have the method which controls its movement (just to right for now). when i instantiate the object i call its moveRight method which should alter its xy coordinates. then every second i rendor it to the screen in a separate function which calls for the objects xand y properties

//here i define object

function Mechanoid(){

//object properties

this.life=100;
this.x=500;
this.y=200;
this.anArray=new Array(0, 0); //can i create an array like this? i know it works when called from   outside the object



//object methods

this.moveAround=function(){ 

   var clock=setInterval(Function ()  {
       this.x=this.x+1;   //console log says undefined
       this.y=this.y+1;

       this.anArray[0]=this.x;  //console says cannot read propety of null
       this.anArray[1]=this.y;
        },1000);
  }  

}


 //then instanciate  

 var mech=new Mechanoid;
 mech.moveAround();   // calls method to change object properties


//A request for the x any y coordinates of mech object will be called in a render function where it
//will be drawn to the canvas.

Can anyone tell me why the properties are not accessible from within the object method? and what i have to do to access them? thanks... there's probably a bracket missing in the syntax or something I wrote it on the fly i don't think theres a syntax error in the original code , and i dont think thats the problem.

1

5 Answers 5

2

When you use window.setInterval (setInterval is shorthand for window.setInterval), you need to maintain a reference to your object.

When your callback function is executed, this doesn't refer to the object where the setInterval call originated from. window.setInterval invokes your callback function in a different context, namely the context of window.

One solution is to use var self = this;. While the value of this changes according to context, self is an arbitrary variable that maintains a reference to whatever object you assign to it.

this.moveAround = function () { 
    var self = this;
    var clock = setInterval(function () {
        self.x = self.x + 1;
        self.y = self.y + 1;
        self.anArray[0] = self.x;
        self.anArray[1] = self.y;
    }, 1000);
}

Also, you need to change the "F" in "Function" to a lowercase f (function, not Function).

EDIT:

You can also use Function.prototype.bind in ES5 environments. It returns a function that executes with its this set to an object (in this case, the object that invoked moveAround).

this.moveAround = function () {
    setInterval(function () {
        this.x = this.x + 1;
        this.y = this.y + 1;
        this.anArray[0] = this.x;
        this.anArray[1] = this.y;
    }.bind(this));
}

JavaScript's this has been anecdotally-referred-to-as "broken". window.setInterval is a prime example of where confusion arises. Always be aware of the context in which "this-functions" execute.

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

Comments

0

This is all about scope.

function Mechanoid() {

    var self = this; // cache this

    // bla bla

    this.moveAround = function() {

        var clock = setInterval(function () {
            self.x = self.x + 1;   // no longer undefined
            self.y = self.y + 1;

            // continue this way

      }        
   }        
}

1 Comment

Actually, this isn't scope. (pun intended)
0

You have two errors:

  1. you can't refer to this when you're nested two levels below the object (the other solutions show you how to work around it using var that = this; one level above)
  2. you wrote Function using capital F - change to lower case!

Comments

0

Inside setInterval handler this refers to window. You either need to use closure:

this.moveAround=function(){ 
   var self = this;
   var clock=setInterval(function ()  {
       self.x=self.x+1;   //console log says undefined
       self.y=self.y+1;

       self.anArray[0]=self.x;  //console says cannot read propety of null
       self.anArray[1]=self.y;
        }, 1000);
  }      
}

or bind a context to function:

this.moveAround=function(){ 
       var clock=setInterval(function ()  {
           this.x=this.x+1;   //console log says undefined
           this.y=this.y+1;

           this.anArray[0]=this.x;  //console says cannot read propety of null
           this.anArray[1]=this.y;
            }.bind(this), 1000);
      }      
    }

A fiddle.

Comments

0

You lost the context (this) in the setInterval function. Try :

this.moveAround=function(){ 

   var that = this;
   var clock=setInterval(function ()  {
       that.x=that.x+1;   
       that.y=that.y+1;

       that.anArray[0]=that.x;  
       that.anArray[1]=that.y;
        },1000);
  }  

}

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.