This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 8 years ago.
I tried searching for this for about an hour and can't seem to find a solution that works for me. I have a function (Function2) inside an object that is called by an interval. Function2 cannot find Function1, and is saying the method does not exist. Why might this be, or what is wrong with my syntax?
var ClassA = function ()
{
this.attribute = "";
this.function1 = function()
{
alert("Function 1");
};
this.function2 = function()
{
alert("Function 2");
this.function1(); <----- Does not exist?
};
this.function3 = function()
{
setInterval(this.function2, 5000);
};
};
var CLASS_A = new ClassA();
CLASS_A.function3();
The setInterval behaves asynchronously. When you provide this.function2 as parameter to setInterval, you're basically providing a callback method. When setInterval has reached 5000 it calls your callback method.
The "this" keyword changes depending on the context. The callback context is very different from your object's "ClassA" context. It's not the same "this".
The trick is to do this:
var ClassA = function(){
var that = this;
//And then everywhere else use that instead of this.
that.function1 = function() { ...
that.function2 = function() { ...
that.function1
that.function3 = function ....
}
Good luck.
You have to look carefully about what this means in JavaScript and in what context your function is being called. You can ensure that the context is what you intend by using the bind method of Function, as in the following edit:
var ClassA = function ()
{
this.attribute = "";
this.function1 = function()
{
alert("Function 1");
};
this.function2 = function()
{
alert("Function 2");
this.function1(); // Exists but only on the ClassA, not on Window
};
this.function3 = function()
{
setInterval(this.function2.bind(this), 5000);
};
};
var CLASS_A = new ClassA();
CLASS_A.function3();
Related
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 4 years ago.
I don´t get why "this" in this case returns "NaN" :
function Counter() {
this.num = 0;
this.timer = setInterval(function add() {
this.num++;
console.log(this.num);
}, 1000);
}
And in this one it refers to "this.value":
function foo() {
this.value = 'Hello, world';
this.bar = function() {
alert(this.value);
}
}
var inst = new foo();
inst.bar();
I get that in the first case "this" is pointing to the Window object, I just don´t get why that´s the case.
Inside setInterval this will be completely new and it will have no idea about Counter. You can use bind to pass the context this to setInterval
function Counter() {
this.num = 0;
this.timer = setInterval(function add() {
this.num++;
console.log(this.num);
}.bind(this), 5000);
}
Counter()
Alternatively you can also use arrow function
function Counter() {
this.num = 0;
this.timer = setInterval(() => {
this.num++;
console.log(this.num);
}, 5000);
}
Counter()
The setInterval function barely looks like this:
function setInterval(callback, time, ...args) {
// native complicated code
callback(...args);
}
What matters here is the call (callback(...)), as JS determines the context by how you are calling the function. In your second example the context of bar is inst as you call it as inst.bar(), so you directly tell js what this is. If you call a function direclty, e.g.
const bar = inst.bar;
bar(); // call without context
you don't specify a context, and therefore this defaults to window
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
Improve this question
I have a class in JavaScript (MyClass) which exposes two public functions (funA and funB) as shown:
var MyClass = function(){
this.funA = function(){
console.log("function A");
this.funB();
};
this.funB = function(){
console.log("function B");
};
};
var myObj = new MyClass();
Note how funA calls funB using 'this' keyword.
The following works:
myObj.funA();
But this does not:
var anonymousFun = function(fn){
fn();
}
anonymousFun(myObj.funA);
The reason is when funA calls funB using 'this', the 'this' is set to global context (instead of MyClass) and funB does not exist at global level.
The error is:
Uncaught TypeError: this.funB is not a function
The simplest solution that I tried to avoid the issue is to use a variable 'that' inside MyClass and initialize it to 'this'. Then, use that.funB instead of this.funB inside funA:
var MyClass = function(){
var that = this;
this.funA = function(){
console.log("function A");
that.funB();
};
this.funB = function(){
console.log("function B");
};
};
Is this a correct approach?
Are there any better solutions available?
If you're compiling your JS with Babel you can use class property initilizer syntax to create functions that are bound to this:
class MyClass {
funA = () => {
console.log('function A')
this.funB()
}
funB = () => {
console.log('function B')
}
}
You can use the Function.bind method to attach an object which is to be used as "this" when the function is called.
anonymousFun(myObj.funA.bind(myObj));
It's more like an opinion based question. Though, this might help you in your development. You can use bind or call. Here's an example with call:
var MyClass = function(){
this.funA = function(){
console.log("function A");
this.funB();
};
this.funB = function(){
console.log("function B");
};
};
var myObj = new MyClass();
var anonymousFun = function(fn){
fn.call(myObj)
}
anonymousFun(myObj.funA)
A little better:
var anonymousFun = function(context, fn){
fn.call(context)
}
anonymousFun(myObj, myObj.funA)
Define the functions using identifiers accessible within the scope of the constructor, then add them to the Object at the end. this may change depending on context, but a closure is a closure and references to variables accessible to the function will not change.
var MyClass = function(){
function funA(){ // no `this`
console.log("function A");
funB(); // no `this`
};
function funB(){ // no `this`
console.log("function B");
};
Object.assign(this, { funA, funB });
};
var instance = new MyClass();
instance.funA();
instance.funB();
var lonely = instance.funA;
lonely(); // no longer attached to an object, but can still access funB();
You can just use arrow functions instead. The reason that this becomes a window object is due to a different closure. If you use arrow functions when defining the functions, you with retain the same closure through out the class.
var MyClass = function(){
this.funA = ()=>{
console.log("function A");
this.funB();
};
this.funB =()=>{
console.log("function B");
};
};
This code works as expected
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 6 years ago.
Main concern is efficiency.
I am working on javascript scopes and one thing that I am confused about is this inside a function.
I have read many answers and I understand them. But what I am concerned about is efficiency. Have a look at my code.
class Fancy {
constructor () {
}
checkScope (callback) {
console.log('Inside checkScope');
callback ();
}
}
class Prog {
constructor () {
this.name = 'myProg';
this.fancy = new Fancy ();
}
run () {
var that = this;
this.fancy.checkScope(function () {
console.log('Name ', that.name);
});
}
}
var prog = new Prog ();
prog.run();
Now in run() I am storing reference of this in a local variable that. This is working for me. But is it safe? Is it efficient? If no, please suggest me a good strategy/trick.
Thanks :)
Yes it is safe, but you can use the new arrow syntax.It preserve the this.
class Fancy {
constructor () {
}
checkScope (callback) {
console.log('Inside checkScope');
callback ();
}
}
class Prog {
constructor () {
this.name = 'myProg';
this.fancy = new Fancy ();
}
run () {
// Here your don't need var that = this,
// because the arrow function gets the same this
this.fancy.checkScope( () => {
console.log('Name ', this.name);
});
}
}
var prog = new Prog ();
prog.run();
Every simple function has it's this, in your case your
function () {
console.log('Name ', this.name); // this is undefined in 'strict mode'
}
has its own this.So you need to keep the this outside the function and use with alias in the function.In ES6 there is a new arrow syntax function.Arrow functions don't override the this. In your case
run () {
this.fancy.checkScope( () => {
console.log('Name ', this.name);
});
}
the this in the run function and in the parameter function are the same. It means that in the arrow function scope the this refers to that this in which the arrow function was defined.
In the case of efficient, you don't need an extra variable.You don't pollute the local scope with an extra variable. In the performance there is no affect.
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 8 years ago.
I am trying to call a function via this reference inside of jquery scope:
var Person = function(){
this.hello = function(){
console.log("hello!");
}
this.jump = function(){
$('.jump').on('click', function(){
this.hello();
});
}
}
Then I do:
var p = new Person();
When I click over the .jump element, the console prints an error describing that hello is not a function. I am not sure what is happening here, I am assumming that this is trying to call a function inside of jquery (not sure about it).
So, googling a little bit I found the Jquery.proxy() function that could be helpfull in my situation, but every time I try to understand it my head want to explote.
Use $.proxy() like so:
var Person = function(){
this.hello = function(){
console.log("hello!");
}
this.jump = function(){
$('.jump').on(
'click',
$.proxy(
function() {
this.hello();
},
this
)
);
}
}
Passing this as the 2nd argument to $.proxy() sends that context as the value of this inside the function defined in the first argument.
Try this,
var self = this;
this.jump = function(){
$('.jump').on('click', function(){
self.hello();
});
}
when you refer to "this" inside onclick, by default this refers to the DOM element found in the value of event.target
$('.jump').on('click', function(event) {
this.hello() /// <<-- this == event.target =~ $('.jump')
}
so, fortunately, you can use a closure
var self = this;
this.jump = function(){
$('.jump').on('click', function(){
self.hello();
});
}
This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
Explanation asked about the value of 'this' in Javascript [duplicate]
(2 answers)
Closed 8 years ago.
Simple question. Why do we have set that = this? If we dont, we are in the global scope...but why?
var myObj = {
specialFunction: function () {
},
anotherSpecialFunction: function () {
},
getAsyncData: function (cb) {
cb();
},
render: function () {
var that = this;
this.getAsyncData(function () {
// this now refers to global scope....why?
that.specialFunction();
that.anotherSpecialFunction();
});
}
};
myObj.render();
Writing that = this doesn't change the scope. The way the anonymous function is called will always end up with this being global object,* because that's exactly what the spec says should happen. Using that = this is just a workaround.
You could make this always point to myObj by using Function.call:
var myObj = {
specialFunction: function () {
},
getAsyncData: function (cb) {
cb.apply(this);
},
render: function () {
this.getAsyncData(function () {
this.specialFunction();
});
}
};
and/or using Function.bind:
var myObj = {
specialFunction: function () {
},
getAsyncData: function (cb) {
cb();
},
render: function () {
function callback() {
this.specialFunction();
}
this.getAsyncData(callback.bind(this));
}
};
* Unless you're in strict mode, in which case this is undefined.
take a look at the this keyword in JavaScript and how it works. I’m sure we’ve all come across this issue:
$("myLink").on("click", function() {
console.log(this); //points to myLink (as expected)
$.ajax({
//ajax set up
success: function() {
console.log(this); //points to the global object. Huh?
}
});
});
this is a variable that is automatically set for you when a function is invoked. The value it’s given depends on how a function is invoked. In JavaScript we have a few main ways of invoking functions. I wont talk about them all today, but just the three ways most people use them; either when a function is called as a method, or on it’s own, or as an event handler. Depending on how a function is invoked, this is set differently:
function foo() {
console.log(this); //global object
};
myapp = {};
myapp.foo = function() {
console.log(this); //points to myapp object
}
var link = document.getElementById("myId");
link.addEventListener("click", function() {
console.log(this); //points to link
}, false);
Doing $("myLink").on("click", function() {}) means that when the element is clicked, the function is fired. But this function is bound as an event handler, so this is set to the reference to the DOM element myLink. The success method you define within the Ajax request is just a regular function, and as such when it’s invoked, this is set to the global object, as it is when any function that’s not an event handler or an object method is.
$("myLink").on("click", function() {
console.log(this); //points to myLink (as expected)
var _this = this; //store reference
$.ajax({
//ajax set up
success: function() {
console.log(this); //points to the global object. Huh?
console.log(_this); //better!
}
});
});
Source: http://tinyurl.com/melbl92
EDIT: in JavaScript the "this" context depends on how your function is called, example:
function helloWorld()
{
console.log(this);
}
And here two ways to call this function:
new helloWorld(); note that if you call your function in this
way, the context of this will be the context of the function +
prototype, so your console will show this: helloWorld {}
helloWorld(); if you call your function without of the "new",
the context of "this" will be global(Window), so your console will show
this: Window about:home
Ok, with this little explanation i will try to explain now why you
have sometimes to use self/that...
Imagine that you want to use this.name inside this.hello function. Like I said before, the context of "this" depends on how your function is called, so if you want to ensure that this.name inside of this.hello function refer to this.name outside is recommended that you use self/that to avoid what happens bellow
function helloWorld(){
var self = this;//or that = this
this.name = "YourName"
this.hello = function(){
console.log(this); //the context of "this" here will be: "hello {}"
return this.name; //undefined, because you don't have name attribute inside hello function
}
new this.hello(); //note how hello is called here...
}
var test = new helloWorld();
And here a good explanation about context x scope:
http://ryanmorr.com/understanding-scope-and-context-in-javascript/