Simple Javascript object scope issue [duplicate] - javascript

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/

Related

How can i use varaible from outer scope of the callback function [duplicate]

This question already has answers here:
How do JavaScript closures work?
(86 answers)
Closed 3 years ago.
How do I use the variable from the outer scope of the function. I have created this simple example here
var view = {
init(){
const targetOne = document.querySelector(".targetOne");
const targetTwo = document.querySelector(".targetTwo");
var val = "outer scope";
targetOne.addEventListener('click', (e) => {
console.log('target one', val)
});
targetTwo.addEventListener('click', this.handleEvent);
},
handleEvent(e) {
console.log('targetTwo ', val);
}
}
view.init();
JS fiddle link: https://jsfiddle.net/jr7b521x/50/
For the targetOne callback I can use the variable val, but when i define a function for the targetTwo callback, that variable val is not defined in the scope. I feel like I am missing something very simple here, I refreshed on scope chaining and closure but I am not able to get it
the variable val is within the scope of the init () function
for you to get it in the handleEvent function you will need to pass it by parameter or it must be a property of the view object

Method called by other method with setInterval can not access object property in js [duplicate]

This question already has an answer here:
passing this.method in setTimeout doesn't work?
(1 answer)
Closed 7 years ago.
I wrote a object constructor function with two methods, one of them calls the other via setInterval(functionName, interval), and the called function fails to get the objects properties.
I wrote a simple example on codepen: http://codepen.io/AttilaVM/pen/ZQPVEy
function Test(value) {
this.value = value
this.action = function testAction() {
console.log(this.value); // gives undefined!
}
this.play = function testPlay() {
setInterval(this.action, 500);
}
}
var test = new Test(20);
test.play();
If the method is called without setInterval it works as expected. Why is it different? How can the called method access the object's properties?
this refers to window as it is being call in setInterval(window.setInterval)
To pass the current context, Use .bind(this), The bind() method creates a new function that, when called, has its this keyword set to the provided value
function Test(value) {
this.value = value
this.action = function testAction() {
console.log(this.value);
}
this.play = function testPlay() {
setInterval(this.action.bind(this), 500);
}
}
var test = new Test(20);
test.play();

Unable To Access Private Properties In JavaScript Facade Pattern [duplicate]

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.

How to circumvent the ES6 Class scoping issue with 'this' key word [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
How do I write a named arrow function in ES2015?
(8 answers)
Closed 7 years ago.
For example in the Class constructor:
Socket.on('user:join', onUserJoin);
'onUserJoin' is declared as a method of the class but is being called by socket.io so the 'this' is not my Class. A way to resolve this is to use the '=>' function.
example:
Socket.on('user:join', (data)=>{
this.isOnline = true;
});
Now 'this' is my class, but how do I reference this anonymous function to unsubscribe ?
socket.removeListener('user:join', ????);
I did try this:
let self;
class RoomController {
constructor() {
self = this;
}
...
}
and reference the self in the methods but the self was being shared across sockets...
naming the anonymous function could solve it but I preferred for my case the bind option.
You can use Function.prototype.bind.
Socket.on('user:join', onUserJoin.bind(this));
This ensures that onUserJoin has the correct context, which will be the instance of your class.
You can always bind the arrow functions to the names.
For example,
class RoomController {
constructor() {
this.flag = true;
}
// Assign the arrow function to the name `setFlag`
setFlag = (v) => this.flag = v;
}
let r = new RoomController();
function tester(func) {
func(false);
console.log(r.flag);
// false
func(true);
console.log(r.flag);
// true
}
// Now you can pass the function around, `this` will still refer the object `r`
tester(r.setFlag);

Javascript handler reference to environment it was defined in [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 8 years ago.
In one of my classes, a method performs AJAX requests. In the callback function of a request, I need to call another method of my object, using this. But this does not refer to my object in this context, so I don't know how to do... Is it only possible ?
To clarify, please consider the following code :
function MyClass(arg) {
this.foo = arg;
}
MyClass.prototype = {
myMethod: function() {
console.log("I am myMethod");
},
myGet: function (){
$.get("http://example.iana.org/",function(data){
this.myMethod(); // does not work, because 'this' does not refer to my object
});
}
}
var obj = new MyClass("Javascript is complicated");
obj.myGet();
You can define a variable to store this in the closure :
myGet: function (){
var _this = this;
$.get("http://example.iana.org/",function(data){
_this.myMethod();
});
}
or use $.proxy :
myGet: function (){
$.get("http://example.iana.org/", $.proxy(function(data){
this.myMethod();
}, this));
}
or, if you don't do more than calling myMethod in the callback :
myGet: function (){
$.get("http://example.iana.org/", $.proxy(this.myMethod, this));
}
In modern browsers you can also use bind. When I don't have to be compatible with IE8 I do
myGet: function (){
$.get("http://example.iana.org/", this.myMethod.bind(this));
}

Categories