How do I access a constructor "this" variable? [duplicate] - javascript

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 1 year ago.
In my updateCamera(event) function, I am trying to access this.camera as can be shown in my constructor. Unfortunately, it's undefined in that function, I assume it's a scope issue, but I'm not sure how to solve it. Any ideas? Thank you.
export default class Experience {
constructor(options = {}) {
this.camera = new Camera();
// removed unnecessary stuff
this.onMouseDrag();
}
updateCamera(event) {
console.log(this.camera); //Prints "undefined" in the console
this.camera.position.x = (event.clientX / window.innerWidth) * 2 - 1;
}
onMouseDrag() {
window.addEventListener("mousedown", () => {
window.addEventListener("mousemove", this.updateCamera);
});
window.addEventListener("mouseup", () => {
window.removeEventListener("mousemove", this.updateCamera);
});
}

this behaves confusingly in class components.
When binding to a method (your event listener), this is not bound by default. To fix your issue, change this.updateCamera to this.updateCamera.bind(this) or use an anonymous function (()=>this.updateCamera()).
You can also bind this to your functions in your constructor to reduce confusion like this:
this.updateCamera = this.updateCamera.bind(this);

Related

setInterval returns undefined OR scope of returned value wrong [duplicate]

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)

Using 'this' inside of an observer callback [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 1 year ago.
I have an Angular application that I've just updated from v8 to v12.
The way I handled responses to observables is now deprecated, and while I have changed my code, 'this' no longer works inside the callback and I'm wondering what is the best approach to solve this?
This is how I used to handle observables;
this._trialService.currentTrial().subscribe(trial => {
this.trial = trial;
this.loadVisitDetails()
}, error => {
this._alertService.showWarningAlert(error.error.title);
});
I have changed it to this;
this._trialService.currentTrial().subscribe({
next(trial) {
this.trial = trial;
this.loadVisitDetails()
},
error(error) {
this._alertService.showWarningAlert(error.error.title);
}
});
Because the code no longer uses arrow functions, this no longer refers to the parent class so I am no longer able to access properties and methods on that parent class.
Is there a way to get around this, or will I have to create a variable outside of the callback that will refer to this?
const self = this;
this._trialService.currentTrial().subscribe({
next(trial) {
self.trial = trial;
self.loadVisitDetails()
},
error(error) {
self._alertService.showWarningAlert(error.error.title);
}
});
That just seems a bit messy.
You can still use arrow functions for the handlers:
this._trialService.currentTrial().subscribe({
next: (trial) => {
this.trial = trial;
this.loadVisitDetails()
},
error: (error) => {
this._alertService.showWarningAlert(error.error.title);
}
});

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.

Strange Function Behavior with Prototype and Event Listeners - JavaScript [duplicate]

This question already has answers here:
The value of "this" within the handler using addEventListener
(10 answers)
How to access the correct `this` inside a callback
(13 answers)
Closed 5 years ago.
Original Modal
I want to use a universal app object. To this empty object I will add functions as needed. The issue is that some functions will need to all others within the app object.
So, my question is: how do I construct a large object without having to define all functions inside the object at the time of creation? I would like to split up the chunks of code to not have one astronomical long .js file.
There is a simple example of my original code:
var app = {
tow: function () {
return true;
},
one: function () {
return this.tow();
}
};
// app.one() => returns true
Updated Modal
Here is something I found interesting. I was playing around with the prototype modal and discovered something strange. When I use this model I can add functions that can call other added functions. But, when I create an event listener it is unable to run the code. Can anyone explain why this is?
Modified code with unexpected result:
function modal () {}
modal.prototype.one = function () {
return this.two();
};
modal.prototype.two = function () {
return "cool";
};
modal.prototype.init = function () {
document.getElementById('go')
.addEventListener("click", this.one);
}
var app = new modal();
app.init();
// app.one() => returns true
// event listener => returns "TypeError: this.two is not a function"
JSBIN: https://jsbin.com/vureruziza/edit?js,console,output
this.one called as you done refers to addEventListener function, not to your object. This will solve the issue
modal.prototype.init = function () {
var self = this;
document.getElementById('go')
.addEventListener("click", function(){
self.one()
});
}
bind the click function with this cause the function will need the this context, not the window context. Then call your this.one function in de click handler.
function modal () {}
modal.prototype.one = function () {
return this.two();
};
modal.prototype.two = function () {
return "cool";
};
modal.prototype.init = function () {
document.getElementById('go')
.addEventListener("click", function(e){
console.log(this.one())
}.bind(this));
/*
The following wil also be called but your return value
of your this.one function won't be captured. But your code will run.
.addEventListener("click", this.one.bind(this));
Try replacing it with the above and put a debugger statement in this.one
and see that the code will actualy be ran, just not captured to output.
*/
}
var app = new modal();
app.init();
// app.one() => returns true
// event listener => returns "TypeError: this.two is not a function"
<div id="go">go</div>
Use ES6 fat arrow function. Update modal.prototype.init as below -
modal.prototype.init = function () {
document.getElementById('go')
.addEventListener("click", () => this.one());
}
Edit - If you wanted to debug the issue, you could just console.log the this value in function one like so -
modal.prototype.one = function () {
console.log(this);
return this.two();
};
You will most likely see the window object. You will certainly not see the modal object.

Javascript - referring to "this" in function run upon click [duplicate]

This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 7 years ago.
I have a method of an object that is called upon click, and the this unfortunately refers to the window object instead of the object that I want it to be referring to.
I've read a several posts that mention this issue, but I have not found/understood any alternatives for my situation.
Any assistance in which direction to go would be appreciated
JSFIDDLE
var IceCream = function(flavor) {
this.tub = 100;
this.flavor = flavor;
};
IceCream.prototype = {
scoop: function() {
this.updateInventory();
alert("scooping");
},
updateInventory: function() {
this.tub--;
alert(this.tub);
}
};
var vanilla = new IceCream("vanilla");
vanilla.scoop();
$('button').click(vanilla.scoop);
$('button').click(function(){
vanilla.scoop();
});
Change the last line to this should make it work. The $.fn.click function takes a callback, with event as the first argument, and binds the element as this, not window.
------------Edit------------
To make this a little bit cleaner, you can define a function to return a click function. Define your class like so:
IceCream.prototype = {
scoop: function() {
this.updateInventory();
alert("scooping");
},
updateInventory: function() {
this.tub--;
alert(this.tub);
},
makeClickFn: function(){
var self = this;
return function(event){
self.scoop();
};
}
};
And when you need to bind the click function:
$('button').click(vanilla.makeClickFn());
jsfiddle: https://jsfiddle.net/L7e71sLL/
$('button').click(vanilla.scoop.bind(vanilla));
Bind, creates a function whose this variable is bound to the given object. In this case vanilla
Inside $('button').click() the scope will be of the button. So you need to bind the vanilla scope to the onClick function

Categories