By JamesBrownIsDead


2010-01-25 04:44:21 8 Comments

How do I pass context into setTimeout? I want to call this.tip.destroy() if this.options.destroyOnHide after 1000 ms. How can I do that?

if (this.options.destroyOnHide) {
     setTimeout(function() { this.tip.destroy() }, 1000);
} 

When I try the above, this refers to the window.

5 comments

@Sam 2012-10-20 17:18:16

If you're using underscore, you can use bind.

E.g.

if (this.options.destroyOnHide) {
     setTimeout(_.bind(this.tip.destroy, this), 1000);
}

@CMS 2010-01-25 05:40:08

You need to save a reference to the context where the setTimeout function call is made, because setTimeout executes the function with this pointing to the global object:

var that = this;
if (this.options.destroyOnHide) {
     setTimeout(function(){that.tip.destroy()}, 1000);
} 

You can easily prove that setTimeout set this to the global object by:

(function () {
  alert(this); // alerts hello
  setTimeout(function(){
    alert(this == window); // true
  }, 1000);
}).call("hello");

See also:

@John K 2010-01-25 06:00:59

It works. I tested the concept with a jsbin script: jsbin.com/etise/7/edit

@HoldOffHunger 2017-10-20 17:06:51

This code involves making an unnecessary variable (which has function-wide scope); if you correctly passed in this to the function, you'd have solved this problem for this case, for map(), for forEach(), etc., etc., using less code, fewer CPU cycles, and less memory. ***See: Misha Reyzlin's answer.

@Joel Purra 2012-01-10 08:01:31

There are ready-made shortcuts (syntactic sugar) to the function wrapper @CMS answered with. (Below assuming that the context you want is this.tip.)


ECMAScript 5 (current browsers, Node.js) and Prototype.js

If you target browser compatible with ECMA-262, 5th edition (ECMAScript 5) or Node.js, you could use Function.prototype.bind. You can optionally pass any function arguments to create partial functions.

fun.bind(thisArg[, arg1[, arg2[, ...]]])

Again, in your case, try this:

if (this.options.destroyOnHide) {
    setTimeout(this.tip.destroy.bind(this.tip), 1000);
}

The same functionality has also been implemented in Prototype (any other libraries?).

Function.prototype.bind can be implemented like this if you want custom backwards compatibility (but please observe the notes).


ECMAScript 2015 (some browsers, Node.js 5.0.0+)

For cutting-edge development (2015) you can use fat arrow functions, which are part of the ECMAScript 2015 (Harmony/ES6/ES2015) specification (examples).

An arrow function expression (also known as fat arrow function) has a shorter syntax compared to function expressions and lexically binds the this value [...].

(param1, param2, ...rest) => { statements }

In your case, try this:

if (this.options.destroyOnHide) {
    setTimeout(() => { this.tip.destroy(); }, 1000);
}

jQuery

If you are already using jQuery 1.4+, there's a ready-made function for explicitly setting the this context of a function.

jQuery.proxy(): Takes a function and returns a new one that will always have a particular context.

$.proxy(function, context[, additionalArguments])

In your case, try this:

if (this.options.destroyOnHide) {
    setTimeout($.proxy(this.tip.destroy, this.tip), 1000);
}

Underscore.js, lodash

It's available in Underscore.js, as well as lodash, as _.bind(...)1,2

bind Bind a function to an object, meaning that whenever the function is called, the value of this will be the object. Optionally, bind arguments to the function to pre-fill them, also known as partial application.

_.bind(function, object, [*arguments])

In your case, try this:

if (this.options.destroyOnHide) {
    setTimeout(_.bind(this.tip.destroy, this.tip), 1000);
}

@aTei 2015-07-12 13:23:29

Why not default func.bind(context...)? Do I miss something?

@Joel Purra 2015-07-16 14:44:47

@aTei: it's already listed.

@Triynko 2015-12-02 14:38:21

Is it performant to constantly keep creating a new function (which bind does) every time you call this? I have a search timeout that resets after every keypress, and it just seems like I should be caching this 'bound' method somewhere for reuse.

@Joel Purra 2015-12-05 14:54:03

@Triynko: I wouldn't see binding a function as an expensive operation, but if you call the same bound function multiple times you might as well keep a reference: var boundFn = fn.bind(this); boundFn(); boundFn(); for example.

@gumkins 2014-05-26 12:19:38

NOTE: This won't work in IE

var ob = {
    p: "ob.p"
}

var p = "window.p";

setTimeout(function(){
    console.log(this.p); // will print "window.p"
},1000); 

setTimeout(function(){
    console.log(this.p); // will print "ob.p"
}.bind(ob),1000);

@Misha Reyzlin 2012-02-15 17:35:59

In browsers other than Internet Explorer, you can pass parameters to the function together after the delay:

var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);

So, you can do this:

var timeoutID = window.setTimeout(function (self) {
  console.log(self); 
}, 500, this);

This is better in terms of performance than a scope lookup (caching this into a variable outside of the timeout / interval expression), and then creating a closure (by using $.proxy or Function.prototype.bind).

The code to make it work in IEs from Webreflection:

/*@cc_on
(function (modifierFn) {
  // you have to invoke it as `window`'s property so, `window.setTimeout`
  window.setTimeout = modifierFn(window.setTimeout);
  window.setInterval = modifierFn(window.setInterval);
})(function (originalTimerFn) {
    return function (callback, timeout){
      var args = [].slice.call(arguments, 2);
      return originalTimerFn(function () { 
        callback.apply(this, args) 
      }, timeout);
    }
});
@*/

@Triynko 2015-12-02 14:43:12

When creating a class by using the prototype chain and your methods are prototype methods... 'bind' is the only thing that will alter what 'this' is within the method. By passing a parameter to the callback, you don't alter what 'this' is in the function, so such a prototype function could not be written using 'this' within it as any other prototype method could. That leads to inconsistency. Bind is the closest thing to what we actually want, and the closure could be cached in 'this' for higher lookup performance and not having to create it more than once.

Related Questions

Sponsored Content

51 Answered Questions

[SOLVED] Create GUID / UUID in JavaScript?

  • 2008-09-19 20:01:00
  • Jason Cohen
  • 1331687 View
  • 3380 Score
  • 51 Answer
  • Tags:   javascript guid uuid

17 Answered Questions

[SOLVED] How to decide when to use Node.js?

41 Answered Questions

[SOLVED] Check if object is an array?

  • 2011-01-23 18:53:04
  • mpen
  • 1251952 View
  • 2260 Score
  • 41 Answer
  • Tags:   javascript arrays

28 Answered Questions

[SOLVED] Copy array by value

  • 2011-09-20 13:38:08
  • Dan
  • 693422 View
  • 1432 Score
  • 28 Answer
  • Tags:   javascript arrays

29 Answered Questions

[SOLVED] Is JavaScript a pass-by-reference or pass-by-value language?

8 Answered Questions

[SOLVED] How to access the correct `this` inside a callback?

32 Answered Questions

[SOLVED] $(document).ready equivalent without jQuery

  • 2009-04-28 21:51:11
  • FlySwat
  • 859982 View
  • 1696 Score
  • 32 Answer
  • Tags:   javascript jquery

20 Answered Questions

[SOLVED] How can I pass a parameter to a setTimeout() callback?

7 Answered Questions

[SOLVED] What is JSONP all about?

12 Answered Questions

Sponsored Content