This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 4 years ago.
I am trying to understand the bind method and I have written the below code :
//
//Window Context
function Hello(d) {
//Always this reffers to calling context
console.log(d);
}
Hello("ABC");
function Student(sname) {
this.name_n = sname;
this.hello = Hello;
this.printAfter2Seconds = printAfter2Seconds.bind(this);
this.print = function() {
console.log(`Student Name: ${this.name_n}`);
}
}
printAfter2Seconds = function() {
console.log(`Before Set TimeOut - ${this.name_n}`);
//let that = this;
setTimeout(function() {
//console.log(this);
console.log(`After Set TimeOut - ${this.name_n}`);
},2000);
}
function Department(dname) {
this.name_n = dname;
this.hello = Hello;
this.printAfter2Seconds = printAfter2Seconds.bind(this);
}
let s = new Student("ABC");
s.hello(s.name_n);
s.printAfter2Seconds();
let d = new Department("IT");
d.hello(d.name);
d.printAfter2Seconds();
//
If I comment the setTimeout line and the line ending setTimeout like below :
//setTimeout(function() {
//console.log(this);
console.log(`After Set TimeOut - ${this.name_n}`);
// },2000);
I am getting the expected output ABC and IT. But If I include setTimeout I am getting undefined both time. So I am guessing some where I need to invoke bind again. This may not be a trivial example that you use everyday just trying to understand bind.
So I need to understand how to bind the this context of the function inside setTimeout or that is even possible.
Thanks in Advance.
Related
This question already has answers here:
JavaScript setInterval and `this` solution
(9 answers)
How to access the correct `this` inside a callback
(13 answers)
Closed 5 months ago.
I try to store Date.now() after a setIntervall invoked a callback. After that, I'd like to clear the intervall, so it only fires once. All that in a class.
But the variable I store the intervalID in and I hoped would be available "class-wide" keeps "undefined". I am pretty sure I am doing sth awfully wrong with JS scope, but I cannot find out what.
class Signal {
t : number;
private intervallId : number | undefined;
constructor(t : number) {
this.t = t;
}
wait() {
this.intervallId = setInterval(this.signalTriggered, this.t)
console.log("Never executed.")
}
signalTriggered() {
const triggerTime : number = Date.now()
console.log(this.intervallId) /* always undefined */
if (this.intervallId) {clearInterval(this.intervallId)
console.log(triggerTime); }
}
}
var timer = new Signal(2000)
timer.wait()
console.log("Done.") /* Never printed out. */
The problem is the reference of the this, you are losing the original reference of it when passing the method as an argument to setIterval.
You could use an arrow function to wrap the method:
setInterval(() => this.signalTriggered(), this.t)
Or use Function.prototype.bind to assign the reference of this:
setInterval(this.signalTriggered.bind(this), this.t)
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 3 years ago.
Why is this.tick not a number in this script?
var universe;
$(function() {
universe = new Universe();
universe.timeStart();
});
function Universe() {
this.timer = 0;
this.tick = 0;
this.timeStart = function(){
this.timer = setInterval(this.timeForward, 500);
};
this.timeStop = function() {
clearInterval(this.timer);
};
this.timeForward = function(){
this.tick++;
console.log(this.tick);
};
}
https://jsfiddle.net/qhL492w1/
Because you didn't use an arrow function to preserve the execution context that the keyword this points to, so once the function that you're making setTimeout/setInterval call gets triggered, this will be the global scope.
(if you're running this in the browser, this will be window by the time the timeout/interval resolves. You can verify that by doing a console.log(this) in your code).
If you need this to stay the same, use an arrow function to make sure that this keeps pointing at what it's pointing to when you declare the code, rather than when the code executes: setInterval(() => this.timeForward(), 500).
Also, modern browsers support modern JS, with consts and class syntax, so what you're doing in a function may make more sense written as:
class Universe() {
constructor() {
this.timer = 0;
this.tick = 0;
}
timeStart(){
this.timer = setInterval(() => this.timeForward(), 500);
}
timeStop() {
if (this.timer) {
clearInterval(this.timer);
}
}
timeForward() {
this.tick++;
console.log(this.tick);
}
}
const universe = new Universe();
universe.timeStart();
And then loading that with a <script src="yourfile.js" defer></script>, where the defer keyword basically does the same thing that jQuery's $(...) does: it runs the code in your file only after the DOM is done (but before DOMContentLoaded gets triggered), no matter where in the HTML you place that script tag.
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 4 years ago.
hi I want to use 'this' variable in setInterval in a jquery function
I write '// this code don't work' after don't worked line
(function($)
{
$.fn.rotate=function () {
var counter=0;
var timer=setInterval(function () {
counter++;
var transform='rotate('+counter+'deg)';
$(this).css('transform',transform); // this code dont work
if(counter>=300)
clearInterval(timer);
},1);
return this;
};
$('#socialNetworks i').rotate();
}(jQuery))
thanks Alot
Using the arrow function when defining the function maintains the this context in which the function has been called. Thus you would be able to access this inside the function correctly.
( $ => {
$.fn.rotate=function () {
var counter=0;
var timer=setInterval(function () {
counter++;
var transform='rotate('+counter+'deg)';
$(this).css('transform',transform); // this code dont work
if(counter>=300)
clearInterval(timer);
},1);
return this;
};
$('#socialNetworks i').rotate();
})(jQuery)
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 7 years ago.
I have following code :
function A() {
this.value = 'a_value';
}
A.prototype.getValue = function(){
console.log(this.value); // got undefined, expected 'a_value'
}
setTimeout(new A().getValue, 100);
why i get this.value as undefined.?
and how how do i access this.value?
EDIT : i am not allowed to change the setTimeout line (last line) of code.
Hint: have you tried console.log(this);?
You are only passing the getValue function to setTimeout, not its context. Something like this would work: setTimeout(function() {new A().getValue();},100); But without changing that last line, there's basically nothing you can do.
you can avoid using the this altogether and not having this kind of problems with the following technique :
var A = function () { // no new no this
var value = 'a_value';
var getValue = function(){
console.log(value);
};
return Object.freeze({
getValue ,
});
};
setTimeout(A().getValue, 100);
or write
var a = new A();
before, and then
setTimeout(a.getValue.bind(a), 100);
This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 8 years ago.
Below is my javascript code:
function showBranch_init() {
var id_arr = ["jdc_b1","jdc_b2","jdc_b3","jdc_b4"];
for(a=0;a<id_arr.length;a++){
timeoutID = window.setTimeout(function() {
showBranch(id_arr[a]); // <-- Right here
}, 500);
}
}
How can I pass the value of id_arr[a] to showBranch funcion?
Currently the above code returns null for id_arr[a]
by introducing a new scope (by a function call) for each iteration step you can pass the argument like this:
function showBranch_init() {
var id_arr = ["jdc_b1","jdc_b2","jdc_b3","jdc_b4"];
for(a=0;a<id_arr.length;a++){
(function(i) {
timeoutID = window.setTimeout(function() {
showBranch(id_arr[i]); // <-- Right here
}, 500*i);
})(a);
}
}
Updated to fullfill the 2nd req: showBranch() in 500ms steps..
http://jsfiddle.net/HXc4d/
function showBranch_init() {
var id_arr = ["jdc_b1","jdc_b2","jdc_b3","jdc_b4"];
for(a=0;a<id_arr.length;a++){
timeoutID = window.setTimeout(function(idvalue) {
showBranch(idvalue);
}(id_arr[a]), 500);
}
}
EDIT: The problem with your solution is the fact that when the code executes (timeout) id_arr no longer exists in the executing scope, thus leading to undefined result. When sending the variable as an argument it "stays" with the funciton itself, regardless of the executing scope.
function showBranch_init() {
var id_arr = ["jdc_b1","jdc_b2","jdc_b3","jdc_b4"];
timeoutID = window.setTimeout(function() {
for(a=0;a<id_arr.length;a++){
showBranch(id_arr[a]); // <-- Right here
}
}, 500);
}
can you do that?? O_O