1

Can anyone tell me why my 'showDiv_boo' is undefined inside the class´s method? I also can´t access my class´s methods.

Here´s my class 'Blink' class with its properties and methods:

function Blink(div) {
    this.div = div
}
Blink.prototype.counter = 0
Blink.prototype.showDiv_boo = true
Blink.prototype.showDiv = function() {
    this.div.style.visibility = 'visible'
}
Blink.prototype.hideDiv = function() {
    this.div.style.visibility = 'hidden'
}
Blink.prototype.startEngine = function() {
    if (this.showDiv_boo) {
        this.showDiv()
    } else if (!this.showDiv_boo) {
        this.hideDiv()
    }
    this.showDiv_boo = !this.showDiv_boo
    this.counter++
}
Blink.prototype.startEffect = function() {
    this.idEffect = setInterval(this.startEngine, 1000 / 45)
}

So, if I create:

_blink = new Blink(myDiv);
_blink.startEffect();

You can test... the variable 'showDiv_boo', is undefined inside the method.

Even, if I set the showDiv_boo inside the method to true, it won´t call my class´s methods showDiv or hideDiv.

Anyone?

Thanks :)

1

4 Answers 4

5

The reason why is that startEngine is called from setInterval. The way in which this callback is invoked causes startEngine to have a different value for this than startEffect. You need to save this in order to maintain it in the callback. For example.

Blink.prototype.startEffect = function () { 
  var self = this;
  self.idEffect = setInterval(function () { self.startEngine(); }, 1000 / 45);
};
Sign up to request clarification or add additional context in comments.

2 Comments

Hi. I´ve tried to use 'var self' and same thing. showDiv_boo is undefined inside startEngine method.
Think you may not be wrapping it in the anonymous function -- doing both is key. If you don't use the anonymous function self.startEngine and this.startEngine are exactly the same. See my answer for further explaination.
3

You need to:

  1. use var self and call the method via self.startEngine()
  2. use an anonymous function to wrap the call in [1] i.e. function(){ self.startEngine(); }

This is because when you just pass this.startEngine or self.startEngine you are just passing the function startEngine without specifying what this is, which in both cases is supplied by the global conext of DOMWindow.

To give an example...

function startEngine() { 
  ...code omitted... 
};

Blink.prototype.startEngine = startEngine;

Blink.prototype.start = function() {
  setTimeout(startEngine, 0);       // obviously wrong, what is this?
  setTimeout(Blink.startEngine, 0); // actually the same as line above, although not as obvious
  setTimeout(startEngine.bind(this), 0); // works correctly
}

works to add code to the prototype and if used in the anonymous function will work as expected, but if you just use Blink.startEngine as the callback it is exactly the same as using startEngine only the second is more obviously wrong because there's no object it is being called on so you'd expect this to be whatever is supplied by the context.

The other way you could do this without using the anonymous function would be

  Blink.startEngine.bind(self)

Which returns a function that will call startEngine with the correct this same as explicitly creating the anonymous function and wrapping the call to self.startEngine()

Heres a link to a fiddle to play around with the differences: http://jsfiddle.net/bonza_labs/MdeTF/

Comments

0

If you do the following, you will find it is defined

var x = new Blink('hello');
x.showDiv_boo

Javascript uses prototypical inheritance. While showDiv_boo may not be explicitly defined within the instance of Blink that you now have, it does exist within the prototype that Blink inherits from. When you try referencing showDiv_boo from within the object, the Javascript engine realizes the object does not own a member by that name and then will check its prototype.

1 Comment

How can I access 'showDiv_boo' inside 'startEngine' method? Thanks :)
0

Along with setting a temporal variable to store this, you must call the startEngine() function with that variable:

Blink.prototype.startEffect = function(){
   var self = this;
   self.idEffect = setInterval(function(){ self.startEngine.call(self); }, 1000/45);
}

Note the .call(self), which basically calls the function with the variable self, so the variable this in startEngine will be the correct one.

1 Comment

Just calling self.startEngine() is sufficient you don't need to also explicitly bind the call to self again.

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.