Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I lose the context of this in Javascript?

Tags:

javascript

I have this simple code :

var o = {
    a: 1,
    b: 2,
    f1: function ()
    {
        alert(this.b);
    }
}

var o2 = {
    a: 11,
    b: 22,
    f2: function (j)
    {
        j();
    }
}

But running this code :

o2.f2(o.f1) yields undefined. ( while im expecting "22" as a result)

Now, I know that the context has gone somewhere. and hence If I change the code in o2 to :

 f2: function (j)
    {
        j.apply(this);
    }

It does work obviously.

But my question is :

  • In what stage did i lose the context ?

I don't understand : when j() is running , there is a b property in the o2 object.

What am I missing ?

jsbin

like image 716
Royi Namir Avatar asked May 05 '13 06:05

Royi Namir


People also ask

Why this keyword is undefined in JavaScript?

The this keyword of the clickMe arrow function refers to the global object, in this case the window object. So, this. position and this. color will be undefined because our window object does not know anything about the position or the color properties.

How do you change the context of this in JavaScript?

You can't change what this refers to from inside the function. However, you can call a function in a specific context - so that this refers to a specific object - by using call or apply . Show activity on this post. Note "is immutable".

How do you pass this function in JavaScript?

You can use addEventListener to pass this to a JavaScript function.

What is this context in JavaScript?

What is context? Context is always the value of the this keyword which is a reference to the object that “owns” the currently executing code or the function where it's looked at. We know that window is a global object in the browser so if we type this in the console and it should return window object, which it does.


2 Answers

I found Crockford had an excellent description of the way this works. Functions in JavaScript can be invoked in 4 styles :

  1. The "function" style
  2. The "method" style
  3. The "Constructor" style
  4. The "call or apply" style.

I might be getting the exact names wrong there, but the spirit is the same. You should definitely get the book "JavaScript: The Good Parts" if you don't have it.

So anyway - on to your question. The key thing is that the value if "this" is dependant on which style you use.

// function invocation style, 
var f = function() { console.debug(this); }
f(); // "this" is bound to the global object.

// "method" invocation style
var obj = {
    f: function() { console.debug(this); }
};

obj.f(); // "this" is bound to "obj", the object on which the function was invoked

// so important bit is :

var f = obj.f;
f(); // "this" is global object
obj.f() // "this" is obj

In your example you are losing "this" because of the way you are invoking the function.

like image 133
Woody Avatar answered Sep 20 '22 08:09

Woody


If you do it like as follows,

function will be called in o2 context

var o2 = {
    a: 11,
    b: 22,
    f2: function (j){
      this.temp = j;
      this.temp();
    }
};

also these will work too:

f2: function (j){
      j.apply(this);
}

f2: function (j){
      j.apply(o2);
}

Otherwise you call it just like an ordinary function out of context.

j Is ripped out of its context and you did no tricky closures on it(which is not your intent) so for making "this" work in it you need a scope. The this scope in your question for j is window, which has no "b" in it therefore you get an "undefined".

like image 25
Volkan Avatar answered Sep 18 '22 08:09

Volkan