简体   繁体   中英

Using $(this) in setTimeout();

I want to set timeouts dynamically in jQuery. The dynamically set timeout functions need to use $("this"), but I can't seem to get it working.

An exmple:

$("div").each(function(){
    var content = $(this).attr('data-content')
    setTimeout("$(this).html('"+content+"')",$(this).attr('data-delay'));
});​

http://jsfiddle.net/qmhmQ/

What is the best way to do this?

$("div").each(function(){
    var content = $(this).attr('data-content'),
        $this = $(this); // here $this keeps the reference of $(this)
    setTimeout(function() {

      // within this funciton you can't get the $(this) because
      // $(this) resides within in the scope of .each() function i.e $(this)
      // is an asset of .each() not setTimeout()
      // so to get $(this) here, we store it within a variable (here: $this) 
      // and then using it

        $this.html(content);
    }, $this.attr('data-delay'));
});​

DEMO

Your code should look like this:

  1. pass a function instead of a string. Explanation: When passing a string to setTimeout you get problems, because it runs in a different scope than you original one, and thus you get errors.

  2. use the jQuery data() method

     $("div").each(function(){ var content = $(this).attr('data-content'), $el = $(this), setContent = function(){ $el.html(content); } setTimeout(setContent,$el.data('delay')); });​ 

You can assign a function to a variable and pass that variable as parameter to setTimeout, this is the cleanest way.

Use closures ( some tutorials ).

Using strings with setTimeout is not a good idea. Also beware this , since it can change its context ( ie. call-site ) if used inside a closure.

If using data attributes you can use the jQuery data function.

 $("div").each(function() { var instance = $(this); var content = instance.data('content'); var method = function() { instance.html(content); }; setTimeout(method, instance.data('delay')); }); 
 div { border: 1px solid black; margin: 5px; height: 1.5em; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div data-content="fus" data-delay="1000"></div> <div data-content="ro" data-delay="2000"></div> <div data-content="dah" data-delay="5000"></div> 

I am just expanding answer one above,

  1. Use class or id to refer div in JavaScript. This will avoid further tag name conflicts in the page.

So your updated HTML is,

<div data-content="fus" data-delay="1000" class="dv"></div>
<div data-content="ro" data-delay="2000" class="dv"></div>
<div data-content="dah" data-delay="5000" class="dv"></div>​

Now your updated JavaScript code is,

$(".dv").each(function(){
    var content = $(this).attr('data-content'),
    $this = $(this);
    setTimeout(function() {
       $this.html(content);
    }, $this.attr('data-delay'));
});​

Where main line is

$this = $(this);

Where we are assigning the current element to our variable used in the setTimeout function.

Please refer this link

Take $(this) out of settimeout and save that in local variable say 'self' just after $("div").each(function(){ this line

var self=$(this);

and use that self further.

The following seems like a good compromise of whitespace, readability and revealing intention.

$('div').each(function(){
    var element = $(this)
    var content = element.attr('data-content')
    var delayms = element.attr('data-delay')
    var action = function() { element.html(content) }

    setTimeout(action, delayms)
})

​ SEE: http://jsfiddle.net/wilmoore/LSs6g/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM