Carl Edwards
Carl Edwards

Reputation: 14434

Variable Scope with setTimeout & clearTimeout

While studying variable scope there has been one thing I can't seem to figure out. For example of two elements. If the first is hovered upon then its sibling appears. If you mouse-out of the initial element the sibling will disappear through a setTimeout which is stored within a variable expression. If you happened to hover over the sibling a clearTimeout function is called and is set to fade out in the callback.

In regards to scope what I'm not understanding is how exactly the timer variable is recognized in the clearTimeout function. I tried to console.log(timer) but just got numeric values. While the following works I'd like to know why and how? In other words how does the second hover method call know what's inside the timer variable since its out of scope?

var timer;

$('p:eq(1)').hide();

$('p').first().hover(function() {
  $(this).next().fadeIn();
}, function() {
  timer = setTimeout(function() {
    $('p:eq(1)').fadeOut();
  }, 1000);
  // console.log(timer);
});

$('p:eq(1)').hover(function() {
  clearTimeout(timer);
}, function() {
  $('p:eq(1)').fadeOut(1000);
});

Upvotes: 1

Views: 2541

Answers (2)

Adam
Adam

Reputation: 2077

The function clearTimeout takes not just a setTimeout, but its ID. Here's what I found it on MDN: enter image description here

So, when you set a timeout, it returns a specific ID for reference and so clearTimeout will work. Again, per MDN: enter image description here

Since you set timer on the global scope, each of your functions has access to it.

Thanks for asking a question that taught me something! (I didn't know setTimeout returned anything)

Upvotes: 1

mike510a
mike510a

Reputation: 2168

Simple.. The timer itself is stored in memory though the 'timer' variable which you have defined in the same scope as the sibling event bindings. Therefore, the timer variable is acccessable by directly calling it with 'timer' in any sibling or child scopes. Had you declared the 'var timer' part within the function like this:

 function() {
  var timer;
  timer = setTimeout(function() {
    $('p:eq(1)').fadeOut();
  }, 1000);

The result would be that clearTimeout(timer) would not be within the scope and result in an unknown member error.

Upvotes: 0

Related Questions