views:

86

answers:

4

The following script produces "Hello", "undefined", "Hello" message boxes:

function action(callback) {
  window.setTimeout(callback, 1000);
}

var obj = { 
  text: "Hello", 
  f: function() { window.alert(this.text); } 
};

obj.f(); // Line 1
action(obj.f); // Line 2
action(function() { obj.f(); }); // Line 3

I looking for explanation why the line marked as "Line 2" produces "undefined" output.

+2  A: 

When you call line2: You are only passing the function into the parameter. Since you are only passing the function, not the whole object, when it is called, this in the function does not refer to obj, thus making this.text undefined.

thephpdeveloper
Actually, _this_ in that context means the global object - in this case, _window_
K Prime
updated explanation
thephpdeveloper
A: 

The second one you pass a function with no scope so this becomes the highest object in the scope chain. The third way you create a closure and call f on the object directly which leaves this with the proper scope.

ChaosPandion
+2  A: 

in JavaScript, this is not bound to the method (like in python). Line 2 results in just the function being called, and this is undefined or not obj

Knio
+1  A: 

Alot of JS libraries do something like this:

if (!Function.prototype.context) {
    Function.prototype.context = function (object) {
        var fn = this;
        return function () { return fn.apply(object, arguments); };
    };
}

To be able to pass/bind this to a handler. So in your case you can do smthg like this

action(obj.f.context(obj));

and receive your 'Hello'. And yes, this is a general way to do something you done in step 3.

NilColor