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.
Related
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 1 year ago.
I am still very confused about JavaScript/TypeScript closure after reading through a number of examples on the web.
Here is the code that I am having trouble with:
let obj = {
message: '222',
printMessage: function() {
return this.message
},
}
console.log(obj.printMessage()); // 222
let func = obj.printMessage;
console.log(func()); // undefined
When I run this code, I am getting error Cannot read property 'message' of undefined.
I know I can run obj.printMessage() directly, but that's not what I want to do. I want to be able to return the printMessage function as a variable and eventually get called by another function.
I feel that the problem is related to closure, I just don't know how to approach it.
Many thanks for your input.
===========================================
Update:
I found the solution to my problem after tinkering with the code for a bit longer.
Here is my solution.
let obj = {
message: '222',
printMessage: function() {
return this.message
},
getPrintMessage: function () {
return () => this.printMessage()
}
}
console.log(obj.printMessage()); // 222
let func = obj.getPrintMessage();
console.log(func());
I created another function to return an anonymous function that calls this.printMessage(). This way I can access the function from outside of the object.
Thanks for everyone's input.
Welcome to the wonders of the this keyword in JS.
The value of this is determined by how a function is called (runtime binding). In your example, this is a method on an object that doesn't have a reference.
You can use call or bind methods to bind the this value or in this case could also take advantage of getters and setters.
let obj = {
message: '222',
get mess() {
return this.message
}
}
const currentMessage = obj.mess
// Both return the same thing
currentMessage
obj.mess
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);
}
}
}
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 8 years ago.
Consider my following object and method:
function ModalPopupWindow() {
this.Modal = false;
function __InitModalPopUp(height, width, title) {
if(this.Modal != true){
divOverlay.onclick = function() { window.parent.HideModalWindow(); };
}
}
}
Whey I try to assess this.modal property inside the init function on a ModalPopupWindow object, 'this' is referencing to Window, not the object's property. How can I get that value?
There are several techniques, including a method named bind(). Another approach is to create a variable and bind it to the parent context before the function is called. I have seen people use a variable named underscore this (_this)
function ModalPopupWindow() {
//Capture the correct "this"
var _this = this;
this.Modal = false;
function __InitModalPopUp(height, width, title) {
//Use _this here
if(_this.Modal != true){
divOverlay.onclick = function() { window.parent.HideModalWindow(); };
}
}
}
I recommend this article if you want to learn more about how JavaScript works and how to use bind().
http://javascriptissexy.com/javascript-apply-call-and-bind-methods-are-essential-for-javascript-professionals/
This question already has answers here:
Javascript: Overwriting function's prototype - bad practice?
(6 answers)
Closed 8 years ago.
When protyping functions (in most code I've seen) they are generally written like so:
function MyFunc() { }
MyFunc.prototype.render1 = function() { };
MyFunc.prototype.render2 = function() { };
MyFunc.prototype.render3 = function() { };
However this can be shortened like so:
function MyFunc() { }
MyFunc.prototype = {
render1: function() { },
render2: function() { },
render3: function() { }
};
From my understanding the shortended way will completely override the functions prototyped properties, as opose to adding one. Is there any other downsides to writing the protoyped functions in this manner?
I don't know any issues writing the second way - which I use also - because root prototype is Object, and you are passing an object so...
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 8 years ago.
I have a problem with javascript namespaces.
I want to call secondMethod from ajax callback function but I don't know how to get reference to it.
I have done it like that yet. But variable thisReference seems to me awkward. And whole construction is difficult to read.
So I'm writing there for help and answer how to rewrite it better.
var testObject = new TestObject();
testObject.firstMethod("hello world!");
function TestObject() {
var thisReference = this;
this.firstMethod = function(firstParam) {
ajaxFunc(firstParam, function(ajaxResult) {
thisReference.secondMethod(ajaxResult);
});
};
this.secondMethod = function(secondParam) {
alert("secondMethod " + secondParam);
};
}
function ajaxFunc(hello, callBack) {
callBack(hello);
}
Thanks a lot.
Ondra
Something like what you're doing is a common way to do it. Using:
var that = this;
or:
var self = this;
are common names to keep a hold of your original scope.
Another option (which I prefer) is to bind the this object to the method you're calling so that you have access to it in the callback. That would look like this:
this.firstMethod = function(firstParam) {
ajaxFunc(firstParam, function(ajaxResult) {
this.secondMethod(ajaxResult);
}.bind(this));
};
Hope that helps.