Why do I lose the context of this in Javascript?

后端 未结 3 1078
北荒
北荒 2020-12-10 14:20

I have this simple code :

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

var o2 = {
    a: 11,
    b: 22,
    f2: f         


        
相关标签:
3条回答
  • 2020-12-10 14:35

    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.

    0 讨论(0)
  • 2020-12-10 14:49

    Check this tests:

    o.f1(); // alerts 2
    
    var f3 = o.f1; // (*)
    
    f3(); // alerts undefined
    
    o2.f2(f3); // alerts undefined
    
    f3.apply(o2); // alerts 22
    

    I realize that when you pass a function as parameter the context is lost exactly the same way it's lost in the (*) pointed in the code above.

    What happening is j = arguments[0] = o.f1 and at this point you lose the context.

    When passes a function as a parameter you are just passing the reference in memory to that function. Without bind the context you'll fail the simple j() call. That's why you need to use apply or the this trick showed by Ihsan.

    0 讨论(0)
  • 2020-12-10 14:51

    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".

    0 讨论(0)
提交回复
热议问题