Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't use 'this' inside setInterval

It seems that I can't use this inside of a setInerval function. Why is that? What is a elegant solution?

<html>
<script>
var something = function(tMessage){
    this.message = tMessage;
};

something.prototype = {
    start : function(counter){
       document.getElementById('result').innerHTML += this.message + "+++<br />";
        var looper = setInterval(
            function(){
                // This is printing "undefined"
                document.getElementById('result').innerHTML += this.message + "<br />";
                if(!counter--)
                    clearInterval(looper);
            },
            20
        );
    }
};


window.onload = function(){
    var e = new something("hi");
    e.start(2);
}
</script>
<body>
<div id="result"></div>
</body>
</html>

Edit

Thanks for the answers!! But can anyone explain the difference between sending an argument and setting and extra variable? Any memory issues?

like image 698
Ramzi Khahil Avatar asked Dec 20 '22 13:12

Ramzi Khahil


2 Answers

The problem here is that when your function is invoked this refers to the global object. To preserve the current scope, you could make a closure:

    var looper = setInterval(
        (function(scope){
            return function(){
                // This will no longer be printing "undefined"
                document.getElementById('result').innerHTML += scope.message + "<br />";
                if(!counter--)
                    clearInterval(looper);
            };
         })(this),
        20
    );

Instead of handwaving and trying to explain closures (which I am still in the process of fully mastering), I will direct you to this excellent answer: https://stackoverflow.com/a/111200/1726343

like image 60
Asad Saeeduddin Avatar answered Dec 28 '22 11:12

Asad Saeeduddin


You cannot use this because you are in a new function block. I'm always creating a local variable (I'm sure there's a better way):

var c = this;
setInterval(function(
   c.variable = 1;
), 100);
like image 44
tobspr Avatar answered Dec 28 '22 12:12

tobspr