-1

Examine this code

    var _class=function()
    {
        this.Test=100;
        this.Callback=function(msg)
        {
            alert(msg+"\r\n"+this.Test);
        }
    }

    function run(call)
    {
        call("Hello world");
    }

    var obj=new _class();
    run(obj.Callback);

I got the result :

    [Alert]
    Hello world
    undefined

but when i call obj.Callback("Hello world")

i got expected

    [Alert]
    Hello world
    100

why ?

thank for help

1
  • why not? That is just how js works Commented Jun 15, 2011 at 18:33

2 Answers 2

6

There's no intrinsic relationship between an object and the functions defined "inside" it. The only thing that determines the value of this (called the "receiving" object) in a function call is the way in which the function is called.

  • Call a function with object.func(), and this will be bound to object.
  • Call a function with "call()" or "apply()", and this is determined by the first parameter.
  • If a function is called without any implicit object context, however, as in your "callback" example, then this won't refer to anything your object — it will refer to window (or whatever the global context is).

The trick is that when you want to use a function as if it were a "method" on an object, such that the relationship remains intact even though the function reference has been yanked away from the object, you can pre-bind this in a couple of ways:

  1. You can wrap the function in another function, so that you explicitly retain this in a closure.
  2. You can use ".bind()" to (essentially) do the same thing.

The first way would look like this:

run(function() { obj.Callback(); });

The second way would look like this:

run(obj.Callback.bind(obj));

JavaScript is quite different from languages like C# or Java in this respect. In those languages, a function is sort-of stuck forever in a relationship with its class (or instances of its class). Not JavaScript; it really doesn't matter at all, in fact, where a function is defined. Your "_class" function would be equivalent if it were written like this:

function helloThere() { 
   alert(msg + "\r\n" + this.Test);
}

var _class = function() {
    this.Test = 100;
    this.Callback = helloThere;
};

edit — @jamietre correctly notes that had your "_class" function contained some var declarations or local functions, then there most certainly would be a difference (though not with respect to the way this behaves when "Callback" is invoked).

edit again — Thanks @Koolinc

Sign up to request clarification or add additional context in comments.

5 Comments

Not exactly equivalent. Inner functions have access to the resources of the closure. If there were any private variables in _class then the function helloThere in your example would not be able to access them, because it was defined in a different scope. Example: jsfiddle.net/Bd886
@jamietre yes that is definitely true, but in this case there were no "interesting" local var variables in the function. Had that been the case, then you're right. I'll edit the answer.
If a function is called without any implicit object context, however, as in your "callback" example, then this won't refer to anything -> this would refer to the global object I'd say.
@Koolinc you may be right; I'll do a fiddle. The main point is that you can't rely on it being your own object.
@Koolinc yes you're right, in the couple cases I did (plain function call, "setTimeout()" callback), it's the global (window) object.
1

this.Test is not defined. The scope of this in that context is the callback function.

This is a quick fix:

var _class=function()
{
    var self = this;
    this.Test=100;
    this.Callback=function(msg)
    {
        console.log(msg+"\r\n"+self.Test);
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.