From the MDN Documentation :
The " this " problem
The code executed by setTimeout() is called from a separate execution context for the function from which setTimeout was called . The usual rules apply for setting the this for the function being called, and if you did not set this in a call or using bind , it will by default be a global (or window ) object in non-strict mode or undefined in strict mode. It will not be the same as this value for a function called setTimeout . (Emphasis mine)
Since the functions passed to setTimeout are executed in a different context, this not bound. This means that this actually refers to window (or undefined in strict mode). You essentially make $(window).css(...) , which is not intended.
To combat this, you can use Function.prototype.bind to bind this context, as mentioned above. From the documentation:
The bind() method creates a new function that, when called, has the this keyword set to the provided value
Since this outside the setTimeout function is an element (since jQuery does this for you by explicitly binding this , as we do here), using $(this) will reference the #delay element
$("#nodelay").hover(function() { $(this).css("background-color", 'gray'); }); $("#delay").hover(function() { setTimeout(function() { $("#delay").css("background-color", 'gray'); }.bind(this), 500); });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="nodelay">Test</div> <div id="delay">Test</div>
Alternatively, as already mentioned, grab this before introducing an anonymous function, or explicitly specify an element in the selector. If you are using ES6, another way to do this is to use arrow functions that do not bind their own this , referring to the context of the environment.
Li357
source share