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

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

Related

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

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);

AngularJS scope variable can't be set inside of a timeout [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 3 years ago.
I have a jsfiddle for this issue.
https://jsfiddle.net/uvtw5kp1/4/
$scope.Dropdown = {
open: false,
searchValue: "",
timer: null,
hideIt: function() {
this.timer = $timeout(function() {
alert("timeout happened the value will not change");
this.open = false;
}, 50);
},
hideItNotimer: function() {
this.open = false;
},
showIt: function() {
$timeout.cancel(this.timer);
this.open = true;
}
};
When I call Dropdown.hideItNotimer() on ng-mouseout it has no problem, but when I call Dropdown.hideIt() the variable is not set. I have added an alert to ensure the timer is working, and I've tried doing a scope.apply after. What does work is having a scope level function called within the timer:
like this:
$scope.setDropdownHidden = function(){
$scope.Dropdown.open = false;
}
and call that from within the timeout it works, but I want to avoid this if I can.
What am I missing?
In your timeout function, this does not refer to the Dropdown object, it instead probably refers to the window object. In javascript this always refers to whichever object the function was invoked with, not the object in which it was defined. When $timeout invokes your callback function it will do so with something other than your Dropdown object since it doesn't know about that object.
Related: Javascript closures and this
You need to either capture the value of this in the parent function as a closure variable or bind your callback function to the Dropdown object using angular.bind
Timeout has its own scope since it is a closure, so the $scope.open = false is not updating your controller $scope.open variable, you should avoid using timeout for to update scope variables. You should bind the global scope with using bind as -
hideIt: function() {
this.timer = $timeout(function() {
this.open = false;
}.bind(this), 50);
}

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.

Access this in prototype function after a callback [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 7 years ago.
I have following code :
function A() {
this.value = 'a_value';
}
A.prototype.getValue = function(){
console.log(this.value); // got undefined, expected 'a_value'
}
setTimeout(new A().getValue, 100);
why i get this.value as undefined.?
and how how do i access this.value?
EDIT : i am not allowed to change the setTimeout line (last line) of code.
Hint: have you tried console.log(this);?
You are only passing the getValue function to setTimeout, not its context. Something like this would work: setTimeout(function() {new A().getValue();},100); But without changing that last line, there's basically nothing you can do.
you can avoid using the this altogether and not having this kind of problems with the following technique :
var A = function () { // no new no this
var value = 'a_value';
var getValue = function(){
console.log(value);
};
return Object.freeze({
getValue ,
});
};
setTimeout(A().getValue, 100);
or write
var a = new A();
before, and then
setTimeout(a.getValue.bind(a), 100);

How can I attach a change event handler to a variable? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Listening for variable changes in JavaScript or jQuery
How can I track if this variable has changed?
var ConditionalFlag = 0;
I tried this:
var ConditionalFlag = 0;
$(ConditionalFlag).change(function () {
alert("Changed");
});
ConditionalFlag++;
But to no avail. I have considered using a 25ms timer to check for change like this:
var ConditionalFlag = 0;
function CheckFlag() {
if (ConditionalFlag > 0) {
alert("Changed");
clearInterval(check);
}
}
var check = window.setInterval("CheckFlag()", 25);
ConditionalFlag++;
However, that seems like overkill. Is there a way to attach an event handler to this variable with jQuery or javascript?
If it's a global variable, you can use property accessors in supported environments...
window._conditional_flag = 0;
Object.defineProperty(window, "ConditionalFlag", {
get: function() { return window._conditional_flag},
set: function(v) { console.log("changed"); window._conditional_flag = v; }
});
There's no "event" that gets triggered when a variable changes. JavaScript doesn't work that way.
When does this variable get changed? Just add a call to a function after it does.

Categories