This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 3 years ago.
Long-time .Net developer here, tasked with converting a bunch of old JS code to new ES6 JS modules. I'm trying to run the (you would think) simple code below, but when jumpToVideoNew is called, this.allowVidJump in the delegate function doesn't have access to the class property allowVidJump. I'm trying to set a simple timed delay so calling code can't hammer the jumpToVideoNew function repeatedly. I understand the concept that the variable loses scope, but I've tried setting _this = this; and using _this in the delegate as well with no success. Also tried passing a reference to the variable in to the function and accessing it that way, but also no luck. Spending 2 hours on something this simple is reminding me why I steer clear of javascript when possible.
export class WebUtility {
constructor() {
this.allowVideoJump = true;
this.delay = function () { this.allowVidJump = true; };
}
jumpToVideoNew() {
if (this.allowVideoJump) {
this.allowVideoJump = false;
setTimeout(this.delay, 1000);
}
}
}
Use an anonymous arrow function
The function keyword in JS creates a new scope as well as a new this (the function you just defined === this), so this.allowVidJump is essentially (function() {}).allowVidJump in that scope
Try something like this:
export class WebUtility {
constructor() {
this.allowVideoJump = true;
this.delay = () => { this.allowVidJump = true; }; // anonymous lambda
}
jumpToVideoNew() {
if (this.allowVideoJump) {
this.allowVideoJump = false;
setTimeout(this.delay, 1000);
}
}
}
Related
This question already has answers here:
Node.js ES6 Class unable to call class method from within class method when using Express.js
(1 answer)
Javascript recursion within a class
(5 answers)
How to access the correct `this` inside a callback
(13 answers)
Closed 4 years ago.
A class is defined as follow:
export default class FishGame {
constructor(window) {
.......
this.window = window
......
}
gameloop() {
this.window.requestAnimationFrame(this.gameloop);
var now = Date.now();
this.deltaTime = now - this.lastTime;
this.lastTime = now;
....
}
}
you can see the function gameloop is a recursive call.
I call this function in this way:
function game() {
let fishGame = new FishGame(this);
fishGame.gameloop();
}
while a exception is thrown, could someone tell me why this object is null?:
The problem is that this is lost in the callback. There are a few clean ways of doing it described in this post. One approach is to bind this to the callback, or use an arrow function which has this bound to it automatically:
class FishGame {
constructor() {}
gameloop() {
requestAnimationFrame(() => this.gameloop());
console.log(Date.now());
}
}
new FishGame().gameloop();
class FishGame {
static loop(game) {
function doloop() {
requestAnimationFrame(doloop)
game.gameloop()
}
doloop()
}
constructor() {
self = this;
this.name = "Lamax"
}
gameloop() {
console.log(Date.now()+": "+this.name);
}
}
FishGame.loop(new FishGame());
The problem is that you are calling this, inside the function thats passed as a argument in requestAnimationFrame, try the above snipet
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 4 years ago.
I have this situation
class A {
a(params) {
//some code here
}
b(params) {
//some code here
}
c(params) {
this.a(function(data) {
console.log(this); // undefined
this.b(); // error no function b of undefined
})
}
}
I have tried binding this to 'a' using bind(this) but it says Cannot read property 'bind' of undefined or this is not defined. When I print this, I get class A. I want to call it inside 'a' function.
When you have defined a new function, the meaning of this has been changed inside it. You either need to use an arrow function:
this.a((data) => {
console.log(this); // class A
this.b();
})
or save the reference of this in a local variable:
var self = this;
this.a(function(data){
console.log(self); // class A
self.b();
})
Not sure at which point you are expecting the "b" method execution. I've added jsFiddle here: https://jsfiddle.net/k3jkobae/ and just saw that there was short correct answer while I was wrapping mine :) The arrow function is best suited.
class A {
a( callback ){
console.log('a');
callback();
}
b(params){
console.log('b');
}
c(params) {
this.a( () => this.b() );
}
}
const myClass = new A();
myClass.c();
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 1 year ago.
Normally I'd assign an alternative "self" reference when referring to "this" within setInterval. Is it possible to accomplish something similar within the context of a prototype method? The following code errors.
function Foo() {}
Foo.prototype = {
bar: function () {
this.baz();
},
baz: function () {
this.draw();
requestAnimFrame(this.baz);
}
};
Unlike in a language like Python, a Javascript method forgets it is a method after you extract it and pass it somewhere else. You can either
Wrap the method call inside an anonymous function
This way, accessing the baz property and calling it happen at the same time, which is necessary for the this to be set correctly inside the method call.
You will need to save the this from the outer function in a helper variable, since the inner function will refer to a different this object.
var that = this;
setInterval(function(){
return that.baz();
}, 1000);
Wrap the method call inside a fat arrow function
In Javascript implementations that implement the arrow functions feature, it is possible to write the above solution in a more concise manner by using the fat arrow syntax:
setInterval( () => this.baz(), 1000 );
Fat arrow anonymous functions preserve the this from the surrounding function so there is no need to use the var that = this trick. To see if you can use this feature, consult a compatibility table like this one.
Use a binding function
A final alternative is to use a function such as Function.prototype.bind or an equivalent from your favorite Javascript library.
setInterval( this.baz.bind(this), 1000 );
//dojo toolkit example:
setInterval( dojo.hitch(this, 'baz'), 100);
i made a proxy class :)
function callback_proxy(obj, obj_method_name)
{
instance_id = callback_proxy.instance_id++;
callback_proxy.instances[instance_id] = obj;
return eval('fn = function() { callback_proxy.instances['+instance_id+'].'+obj_method_name+'(); }');
}
callback_proxy.instance_id = 0;
callback_proxy.instances = new Array();
function Timer(left_time)
{
this.left_time = left_time; //second
this.timer_id;
this.update = function()
{
this.left_time -= 1;
if( this.left_time<=0 )
{
alert('fin!');
clearInterval(this.timer_id);
return;
}
}
this.timer_id = setInterval(callback_proxy(this, 'update'), 1000);
}
new Timer(10);
This question already has answers here:
javascript "this" keyword not referring to correct thing
(3 answers)
Closed 7 years ago.
The Problem
In my "private" object for the facade pattern, I am defining methods and properties. When calling a method in this "private" object, I am getting Uncaught Typerror's saying that the method I am calling is not a function.
The Code
var lazySize = (function() {
var _ = {
images: [],
lazySizes: {},
resizeTimeout: null,
pageWidth: document.getElementsByClassName('crop_image')[0].offsetWidth,
resizeHandler: function() {
var i = 0;
for (var image in this.lazySizes) {
if (this.pageWidth < image) {
this.images[i++].src = this.lazySizes[image];
}
}
},
resizeThrottler: function() {
if (!this.resizeTimeout) {
this.resizeTimeout = setTimeout(function() {
this.resizeTimeout = null;
this.resizeHandler();
}, 66);
}
}
};
return {
init: function() {
window.addEventListener('resize', _.resizeThrottler, false);
}
};
}());
lazySize.init();
The Error
Uncaught TypeError: this.resizeHandler is not a function
The Question
Why am I unable to access the resizehandler method while inside resizeThrottler?
My understanding when using var rather than let, is that JavaScript is function scoped, so I am rather puzzled as to why I can't access it.
I am trying to improve my JavaScript, so if I am doing something really bad here, I would be very grateful if someone could point it out.
This is because this does not correspond to what you think it does.
You pass the resizeThrottler method as a reference for the browser to call, but when it does call it, the context is no longer your object, but window, which evidently does not have the same properties.
You could solve this as follows:
window.addEventListener('resize', _.resizeThrottler.bind(_), false);
This way you set the context of the method passed as handler to always run with _ as this.
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 8 years ago.
When test.testHello(helloWorld.sayHello); runs, it doesn't recognize that I have inserted a new greeting is the greeting is undefined. I can use bind to make sure it runs it in the proper scope, I am not really sure why isn't it running in the proper scope to begin with. Could someone explain why this is happening and show me a better solution?
Solution: test.testHello(helloWorld.sayHello.bind(helloWorld));
http://jsfiddle.net/EzabX/
var HelloWorldClass = function() {
this.greetings = [];
}
HelloWorldClass.prototype.addGreeting = function(greeting) {
this.greetings.push(greeting);
}
HelloWorldClass.prototype.sayHello = function() {
document.getElementById('output').innerHTML += this.greetings;
this.greetings.forEach(function(greeting) {
greeting.execute();
})
}
var TestClass = function() {
this.testHello = function(callback) {
alert("TestHello is working, now callback");
callback();
}
}
var main = function() {
var helloWorld = new HelloWorldClass();
var test = new TestClass();
helloWorld.addGreeting({
execute: function() {
alert("Konichiwa!");
}
});
helloWorld.sayHello();
test.testHello(helloWorld.sayHello);
}
main();
Managing the this variable within the prototype function scope when called as a callback can be complicated for novice users. You don't always need a prototype for all functions on a class. If you really want to use a prototype function look at Javascript .bind(this) implementations. Google and Stackoverflow are your friend on that topic. Example: Preserving a reference to "this" in JavaScript prototype functions
Offending code with this referring to DOM Window object and not a HelloWorld instance:
this.greetings.forEach(function(greeting) {
greeting.execute();
})
A non-prototype version that works just great, easy to use. Fiddle: http://jsfiddle.net/EzabX/2/
var HelloWorldClass = function() {
var greetings = [];
this.greetings = greetings;
this.addGreeting = function(greeting) {
greetings.push(greeting);
};
this.sayHello = function() {
document.getElementById('output').innerHTML += greetings;
greetings.forEach(function(greeting) {
greeting.execute();
})
}; }