This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 7 years ago.
I am little bit surprised after seeing the output of below javascript code. Still I do not have clue on why myObj variables have not been used inside own method. If I want to use myObj varaibles, what should be the way?
// The use of the "this" object inside the setTimeout function refers to the Window object, not to myObj
var highValue = 200;
var constantVal = 2;
var myObj = {
highValue: 20,
constantVal: 5,
calculateIt: function () {
setTimeout (function () {
console.log(this.constantVal * this.highValue);
}, 2000);
}
}
myObj.calculateIt(); // 400
//The "this" object in the setTimeout function used the global highValue and constantVal variables, because the reference to "this" in the setTimeout function refers to the global window object, not to the myObj object as we might expect.
because this inside setTimeout is referring to global window context. Create a local variable, often named 'self', in the correct scope instead.
var highValue = 200;
var constantVal = 2;
var myObj = {
highValue: 20,
constantVal: 5,
calculateIt: function () {
var self = this;
setTimeout (function () {
console.log(self.constantVal * self.highValue);
}, 2000);
}
}
myObj.calculateIt(); // 400
Related
This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
What does "this" refer to in arrow functions in ES6?
(10 answers)
Closed 1 year ago.
I'm new to javascript and having trouble understanding the difference between arrow function and normal function when including this keyword, here is the example I read from MDN:
var obj = { // does not create a new scope
i: 10,
b: () => console.log(this.i, this),
c: function() {
console.log(this.i, this);
}
}
obj.b(); // prints undefined, Window {...} (or the global object)
obj.c(); // prints 10, Object {...}
In this example arrow function b() can not access i attribute in the object because it references the window
var obj = {
count : 10,
doSomethingLater : function(){ // of course, arrow functions are not suited for methods
setTimeout( () => { // since the arrow function was created within the "obj", it assumes the object's "this"
this.count++;
console.log(this.count);
}, 300);
}
}
obj.doSomethingLater(); //log 11 on the console
However, in the second example, code within the arrow function can access the count attribute. Both functions are defined within the object but only the second function can access the object's attribute, could someone give me some hints why is that? Thanks in advance!
This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 1 year ago.
Can someone explain to me why the second function call returns undefined? I see no reason for that. The reference of the object method is stored in a variable, so it should be printed out. Why the result is undefined? The first function call is successful and the only difference is that the second one is stored in a variable.
const module = {
x: 42,
getX: function() {
return this.x;
}
};
//1 - returns 42
console.log(module.getX());
//2 - returns undefined
const unboundGetX = module.getX;
console.log(unboundGetX());
Because unboundGetX function is called by the global window variable, unboundGetX() it's like writing window.unboundGetX() so the this will refer to the global scope which is "window" object so it's also like you wrote return window.x which is logically "undefined".
it will be better to bind your scope to the same object like this :
const module = {
x: 42,
getX: function() {
return this.x;
}
};
console.log(module.getX());
const unboundGetX = module.getX.bind(module); // we bind getX function to module scope instead of the global scope (which is the window variable)
console.log(unboundGetX());
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 7 years ago.
I am adapting a controller to the "controller as" syntax.
But while transforming the code, I remarked that I can't access the "scope" variables with this out of a function.
If I understand the concept of this, then this does access the object it is used in.
As example this code:
this.scopeVariable = undefined;
this.fooFunction = function () {
resource.get()
.$promise.then(function (result) {
this.scopeVariable = result.foo;
});
};
So when I try to set the scopeVariable with this, I actually try to access an object from fooFunction, right?
If this is the case, how can I grab an object outside of the function within the function?
Thanks for your answers!
You have this problem because the this keyword changes definition when in a different scope. That means that if you have a simple object e.g.
var a = {
b: function() {
console.log(this); // => will log the value of "a"
setTimeout(function() {
console.log('just some rubbish');
console.log(this); // => will log inner function scope instead of "a"
}, 200)
}
}
a.b(); // to see the results
To prevent this issue from happening you can reassign this to a variable which will stay intact through deeper scopes like this:
this.scopeVariable = undefined;
var self = this;
this.fooFunction = function () {
resource.get()
.$promise.then(function (result) {
// using self. instead of this. makes the difference here
self.scopeVariable = result.foo;
});
};
Capturing the this being the scope in a variable: var that = this:
var that = this;
this.fooFunction = function () {
resource.get()
.$promise.then(function (result) {
that.scopeVariable = result.foo;
});
};
This question already has answers here:
JavaScript setInterval and `this` solution
(9 answers)
Referencing "this" inside setInterval/setTimeout within object prototype methods [duplicate]
(2 answers)
How to access the correct `this` inside a callback
(13 answers)
Closed 5 months ago.
I have a problem in regard to setInterval that I can't figure out.
There is the problem with the scope when calling setInterval or timeout from within an object, but still I can't wrap my head around it.
I tried to put my stuff inside an anonymous function, it won't work.
This is basicly my problem, simplified to the bare bones:
function Scenario(){
var ships = [];
this.ini = function(){
for (var i = 0; i < ships.length; i++){
timeoutID1 = setTimeout(ships[i].ding, 1000);
timeoutID2 = setTimeout(ships[i].bing, 1000);
}
}
this.setShips = function(){
var ship = new Ship("ship");
ships.push(ship);
}
function Ship(name){
this.name = name;
this.ding = function(){
intervalID1 = setInterval(function(){
console.log("ding");
}, 500)
}
this.bing = function(){
var _this = this;
intervalID2 = setInterval(function(){
console.log(_this.name);
}, 500)
}
}
this.setShips();
}
var scenario = new Scenario();
scenario.ini();
http://jsfiddle.net/ancientsion/xkwsn7xd/
Basicly, console.log("ding") works, console.log(_this.name) doesn't.
Why?
This is your problem simplified to bare bones:
var ship = {
name: 'Sheep',
ding: function() {
console.log(this.name);
}
}
setTimeout(ship.ding, 1000); // doesn't work correctly
It may help to see another example to understand why the above doesn't work:
var ding = ship.ding;
ding(); // doesn't work either
In JavaScript this depends on how you call your function. ship.ding() will set this to the sheep object. Bare ding() call will set this to the window object.
You can bind the function to the object you want by using .bind() method. (Function.prototype.bind())
var ding = ship.ding.bind(ship);
ding(); // works
ding is now permanently bound to the sheep object. You can use exactly the same approach with setTimeout:
setTimeout(ship.ding.bind(ship), 1000);
By the time setTimeout() gets around to call your method, it only sees the function and not the invocation context (i.e. the object to bind it to); much like this:
var bing = ships[i].bing;
bing(); // inside bing(), this == window
Basically, you need to provide setTimeout() with a prewired method invocation:
var bound_bing = ships[i].bing.bind(ships[i]);
timeoutID2 = setTimeout(bound_bing, 1000);
The "magic" happens with .bind() as it returns a new function that will have this set up properly.
You should define the value _this in Ship function:
function Ship(name){
this.name = name;
this.ding = function(){
intervalID1 = setInterval(function(){
console.log("ding");
}, 500)
}
var _this = this;
this.bing = function(){
intervalID2 = setInterval(function(){
console.log(_this.name);
}, 500)
}
}
Hoist _this out of the bing function.
you should have
_this = this,
this.bing = function() {
intervalID2 = setInterval(function(){
console.log(_this.name);
}, 500)
}
Javascript is imperative so you need to follow the execution path carefully. In function Ship, this points to a Ship object, in function bing, this points to the global scope (window). You need to save a reference to this so that you can refer back to it in these types of functions.
You put ships[i].bing in setTimeout turns out that the caller of bing is not ships[i] but global, so _this is pointing to global actually.
This question already has answers here:
How do JavaScript closures work?
(86 answers)
Closed 8 years ago.
function setupSomeGlobals() {
// Local variable that ends up within closure
var num = 666;
// Store some references to functions as global variables
gAlertNumber = function() {console.log(1); alert(num); }
gIncreaseNumber = function() { num++; }
gSetNumber = function(x) { num = x; }
}
how can I accesss here gAlertNumber method?
update: this code is the Example 4 in an answer on How do JavaScript closures work?
Assuming you're in a web browser, you have to execute setupSomeGlobal() first.
Then your non-declared handler variables g... will be created under the global object window and you'll be able to execute gAlertNumber() from anywhere in your page.
You could execute setupSomeGlobal() in the body's onload :
<html>
<head>
<script>
function setupSomeGlobals() {
// Local variable that ends up within closure
var num = 666;
// Store some references to functions as global variables
gAlertNumber = function() {console.log(1); alert(num); }
gIncreaseNumber = function() { num++; }
gSetNumber = function(x) { num = x; }
}
</script>
</head>
<body onload="setupSomeGlobals();">
<input type="button" value="Show me more or less the number of the beast" onclick="gAlertNumber();"
</body>
</html>
That said, your method of setting up "global" functions isn't very pretty.
I quite like the pattern described here for example.
Here is an example,
(function() {
console.log(1);
// Local variable that ends up within closure
var num = 666;
var sayAlert = function() { console.log(num); }
num++;
return sayAlert();
})();
This will call immediately after definition.
So with your code,
function setupSomeGlobals() {
var num = 666;
// Store some references to functions as global variables
gAlertNumber = function() {console.log(1); alert(num); }
gIncreaseNumber = function() { num++; }
gSetNumber = function(x) { num = x; }
gAlertNumber();
}
setupSomeGlobals();
Here you can call the child function gAlertNumber() inside your parent function setupSomeGlobals() and you cannot access it outside the parent function.
But you can call this after calling parent function, that means don't call the gAlertNumber() inside parent function. call it after calling parent like,
function setupSomeGlobals() {
// Local variable that ends up within closure
var num = 666;
// Store some references to functions as global variables
gAlertNumber = function() {console.log(1); alert(num); }
gIncreaseNumber = function() { num++; }
gSetNumber = function(x) { num = x; }
}
setupSomeGlobals();
gAlertNumber();
Return an object from setSomeGlobals() that contains the three methods. Through this object you will be able to access the functions of interest and manipulate num and keep its state, but you will not be able to access num directly. This is known as the module pattern, an application of closure.
Well this will work in browser
gAlertNumber is considered being window property.. It would be the same as calling
window.gAlertNumber()
so inside your setSomeGlobals you assign function object to the undefined window property. Than you close the local variable num inside that object which is already created inside window object. Thus you can access it from window scope.