Class scope issue [duplicate] - javascript

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
'this' in function inside prototype function [duplicate]
(8 answers)
Closed 4 years ago.
How do I make my objects property available within the callback?
//entrypoint.js
var DeviceManager = require('./class')
DM = new DeviceManager()
DM.start();
var t = setInterval(function() {
console.log("Module.isLoaded = " + DM.isLoaded);
}, 500);
setTimeout(function() {
console.log("Stopping");
clearInterval(t);
DM.stop();
}, 10000);
//class.js
module.exports = class DeviceManager {
constructor(){
this.isLoaded = false;
this._timer= null;
}
start(){
console.log('starting timer')
this._timer = setInterval( function() {
console.log('timer callback')
this.isLoaded = !this.isLoaded;
},1000)
}
stop() {
console.log('stopping timer')
clearInterval(this._timer)
}
}
Basically this line doesnt work, because it doesnt have access to the correct this I assume.
this.isLoaded = !this.isLoaded
Also, since im all around pretty new at this, any feedback/corrections are very welcome.

Try using an arrow function for your setInterval while it's in the class.
An arrow function expression has a shorter syntax than a function expression and does not have its own this
start() {
this._timer = setInterval( () => {
this.isLoaded = !this.isLoaded;
}, 1000)
}

Related

Javascript this context binding [duplicate]

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.

Javascript clearInterval not working for timer [duplicate]

This question already has answers here:
What is the purpose of the var keyword and when should I use it (or omit it)?
(19 answers)
Closed 6 years ago.
Why is clearInterval() not working? what am I doing wrong? I tried a bunch of things but they don't seem to work out...
var s = 60;
var timer = null;
function Ftimer (){
document.getElementById("sec").innerHTML = s--;
}
document.getElementById("start").onclick = function () {
var timer = setInterval(function(){ Ftimer() }, 1000);
}
document.getElementById("stop").onclick = function () {
clearInterval(timer);
}
var timer makes the scope to the onclick function, not the global variable.
timer = setInterval(Ftimer, 1000);
This is due to you overwriting your initial timer variable here:
document.getElementById("start").onclick = function () {
// this clobbers your previous `timer` assignment
var timer = setInterval(function(){ Ftimer() }, 1000);
}
So fix it by simply removing the var and use the outer scoped timer variable:
document.getElementById("start").onclick = function () {
// this assigns to your previous `timer`
timer = setInterval(function(){ Ftimer() }, 1000);
}

Error when calling a method in a setInterval [duplicate]

This question already has answers here:
Pass correct "this" context to setTimeout callback?
(6 answers)
Closed 8 years ago.
I am having trouble calling methods in a setInterval... Here is a snippet of my code...
var example = function(){
this.animate = function(){
console.log("Animate.");
}
this.updateTimer = function(){ // This is being called...
this.timer = setInterval(function(){
this.animate(); // A "Undefined Is Not A Function" error is being thrown here.
}, 1);
}
}
USE BIND (as #torazaburo said)
maybe best-practice
http://jsfiddle.net/rnrlabs/Lnmex1y7/
var example = function(){
this.animate = function(){
console.log("Animate.");
}
this.updateTimer = function() { // This is being called...
this.timer = setInterval(this.animate.bind(this), 1);
}
}
OR.. USE A CLOSURE
http://jsfiddle.net/rnrlabs/zk6hdnf2/
var example = function(){
var self = this; // this creates a closure
this.animate = function(){
console.log("Animate.");
}
this.updateTimer = function(){
this.timer = setInterval(function(){
// 'this' here means window element.
self.animate();
}, 1);
}
}
you cant not use this in setInterval
use this code
edite this.animate() to example.animate()
use this code
var example = function(){
this.animate = function(){
console.log("Animate.");
}
this.updateTimer = function(){ // This is being called...
this.timer = setInterval(function(){
example.animate(); // A "Undefined Is Not A Function" error is being thrown here.
}, 1);
}
}

How to pass a value from for loop to settimeout function [duplicate]

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

JavaScript context issue using setInterval with prototype [duplicate]

This question already has answers here:
JavaScript setInterval and `this` solution
(9 answers)
Closed 5 months ago.
I'm trying to get my head round this context problem while using prototypal inheritence (which I've not really played with before). I have an AutoScroller object:
function AutoScroller() {
this.timer = null;
}
AutoScroller.prototype = {
stop: function() {
if (this.timer == null) {
return;
}
clearInterval(this.timer);
this.timer = null;
console.log("stop");
},
start: function() {
if (this.timer != null) {
return;
}
this.timer = setInterval(function() { this.move(); }, 3000);
console.log("start");
},
move: function() {
console.log("move");
}
};
On document ready, I initiate everything by doing this:
var scr = new AutoScroller();
$('div.gallery p.stopBtn').bind("click", scr.stop);
$('div.gallery p.startBtn').bind("click", scr.start);
The problems all arise because "this" always refers to 'p.startBtn' and not scr, so when the start function with setInterval is called I'm getting an error "this.move() is not a function".
I know context is a fairly fundamental concept of which I appear to have no idea. Any ideas on how to sort this out?
Change start to this:
start: function() {
if (this.timer != null) {
return;
}
var that = this;
this.timer = setInterval(function() { that.move(); }, 3000);
console.log("start");
}
I finally worked it out... I used a closure in the button click like this:
var scr = new AutoScroller();
$('div.gallery p.startBtn').bind('click', function(x) {
return function() {
x.start();
}
}(scr));
And also implemented the change mentioned by SimpleCoder above.
You can also pass the current object instance in setInterval method, so that it always has the access to 'this'.
Verified on IE11, Chrome, Opera and Firefox.
setInterval(function (objRef) {
objRef.foo();
}, 500, ***this***);

Categories