Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript: got 'undefined' when using 'this' to access outer scope variable in 'private' child function

I have a habit of setting all my variables to its parent scope, instead of calling them implicitly:

function outer() {
    var x, y;
    function inner() {
        var x = this.x;
        x = ...// doing stuff here
        y = ....// implicit calling parent variable
    }
}

so that if I mistype my variable, it won't go to global space. But it seems like declare variable with this within private function will return me undefined:

function f() {
    var x = [0];
    function f1() { 
        console.log('f1:', this.x, x); 
        f2(); 
    }
    function f2() { 
        console.log('f2:', this.x, x); 
    }
    return { x:x , f1:f1 };
}

var foo = f();    
foo.f1();
    //output
    f1: [0] [0]
    f2: undefined [0]

If I understand it correctly, it shouldn't happen, as both f1 and f2 should have access to its outer scope by using this. Is there any concept I am missing here? Or is it something I just have to live with for now?

Update: To clarify, my main concern is why there is the difference between f1 and f2. I prefer to keep f2 hidden because it will do some internal works, and other developers should not use it when they declare something from f().

like image 562
bizi Avatar asked Feb 02 '26 06:02

bizi


1 Answers

Also try this:

function f() {
    var x = [0];
    function f1() { 
        console.log('f1:', this.x, x); 
        f2.call(this); 
    }
    function f2() { 
        console.log('f2:', this.x, x); 
    }
    return { x:x , f1:f1 };
}

var foo = f();    
foo.f1();

This way the context of f2 will be properly set.

In your code this in f2 refers to the window object, because f2 wasn't declared as a method. f1 was declared as a method of the returned object when writing { x:x , f1:f1 }. In f2 x is visible not because it is run in the scope of f() but because f2 gets it as a closure. That means in f2, all variables will be visible that was in the same scope when it was created.

What the this refers to will be set at invocation time. If you run a function as property of an object like foo.f1() it is considered as a method, and this will be set to the object. But when you just invoke a function like f2() the scope will be the same it was invoked in, in your case it is the window object, because foo is a global in the window object.

In f1 this refers to the hidden f(), therefore if you want f2 also be run in that scope you can use f2.call(this). The argument of .call() will be the this of the function when run.

like image 172
Zoltan.Tamasi Avatar answered Feb 03 '26 19:02

Zoltan.Tamasi