3

I'm having some interesting issues with passing in variables from within an object into setTimeout. At first, I tried putting the function I was calling from setTimeout on my object so that I wouldn't have to pass any variables into it (I was hoping it could access my object by itself). That didn't work, apparently because the function somehow became global when I called it from setTimeout, and no longer had access to my object's variables.

This was my next attempt, but it doesn't work either:

function MyObj() {
    this.foo = 10;
    this.bar = 20;
    this.duration = 1000;

    setTimeout(function(){
        AnotherFunction(this.foo, this.bar)
    }, this.duration);
}

So, how exactly can I pass in a variable into setTimeout from within an object? No, AnotherFunction won't be able to directly access MyObj for various unrelated reasons, so that's out of the question too.

Elliot Bonneville
  • 51,872
  • 23
  • 96
  • 123
  • what do you hope to achieve here? what's `AnotherFunction` called for? by convention, constructors start with Capitalized letters. is `AnotherFunction` another constructor? or just a function to be called? – Joseph Mar 17 '12 at 23:21
  • It's very complex, that's why I didn't copy my actual code in here. Basically, 'for real', it's a function called ClearCharacter that clears an ASCII character off the page by calling another object's Draw() function, which overwrites MyObj's Draw() function, which is another function I didn't include here because it was irrelevant but that draws an ASCII character on the page via setting the innerHTML value of a

    element. Like I said, complex and very irrelevant. So yeah, `AnotherFunction` is just a function to be called. =)

    – Elliot Bonneville Mar 17 '12 at 23:23

1 Answers1

7

I think the problem is that when your function executes, this is no longer bound to MyObj. You could try

function MyObj() {
    var that = this;
    this.foo = 10;
    this.foo = 20;
    this.duration = 1000;

    setTimeout(function(){AnotherFunction(that.foo, that.bar)}, this.duration);
}

Or I do have one more idea should that not work.

Adam
  • 5,091
  • 5
  • 32
  • 49
  • @Elliot Cool. Just for completeness, I think your other option would be a closure or IIFE (http://stackoverflow.com/questions/8228281/what-is-this-construct-in-javascript) – Adam Mar 17 '12 at 23:24
  • IIFE: that's wicked cool. Thanks again! I'll be able to accept your answer in about a minute. – Elliot Bonneville Mar 17 '12 at 23:25
  • Confusing as hell when you first see it though! – Adam Mar 17 '12 at 23:27
  • Well, it makes a certain degree of sense. I'll never understand *why* it works, though. :P – Elliot Bonneville Mar 17 '12 at 23:28
  • 1
    I have seen this situation arise a decent amount of times where the `this` operator becomes out of scope in dynamic functions. Adam's approach is the same solution I have seen where a variable holds the pointer to the `this` operator which was intended to be used. – Travis J Mar 17 '12 at 23:34
  • 1
    If you need help considering _why_ it works, consider this (no pun intended): The JS expression `this` is not a variable, it is a special expression whose meaning depends on context. So for the code in your question, by the time your callback is called `this` means something *different* than it did within `MyObj`. In Adam's answer, he locked the value of the original object within the variable `that` whose value was the same when the callback ran. TL;DR: In JS `this` is *not a variable*!! It's meaning depends on context. – Ray Toal Mar 17 '12 at 23:35
  • Good explanations. As for the importance of context, consider also if you called `setTimeout` from inside a loop `for(i=0...` and used `i` instead of `that.foo`. It's likely that by the time the function gets called, `i` will have been incremented in the background, and all references in each of the functions would point to the same `i`. – Adam Mar 17 '12 at 23:43