0

I'm confused by what happens with this in this simple code:

function foo() {
    alert(this.a );
}

function doFoo(fn) {
    a = "local";
    fn();
}

var a = "global";

doFoo( foo );

From what I've learned, deFoo is the context object from which foo is called so the alert's message should be "local". That works, unless I declare a inside doFoo:

function doFoo(fn) {
    var a = "local";
    fn();
}

Now the alert message is "global". Can someone explain this to me? I'm new to Javascript.

Rrmm
  • 53
  • 2
  • 7

3 Answers3

1

Few things to be considered:

  1. value of this is determined by how function is called!
  2. If function is called under the global-context, this refers to window (in browser)
  3. If variable is not defined using keyword var, it is global variable.

In your example, a inside function doFoo refers to window.a which is local, overwritten when function is invoked.

function foo() {
  alert(this.a);
}

function doFoo(fn) {
  console.log(window.a);
  a = "local"; //window.a is set to "local"
  fn();
}
var a = "global"; //window.a is "global"
doFoo(foo);

//Few logs to make it clear

console.log(window.doFoo);
console.log(window.a);
Rayon
  • 36,219
  • 4
  • 49
  • 76
  • Why is the function being called under the global-context? I thought the context is determined by the call-site, and the call-site is doFoo. That is what confuses me. – Rrmm Aug 30 '16 at 17:35
  • @Rmm, when you say `var a = "global"` outside, then do `a = "local"` inside the function, the global variable becomes `local`. If you add a `var`, in front it treats it as its own local `a` variable. – Muntasir Alam Aug 30 '16 at 17:38
  • Yes this is a good explanation Rrmm you should accept this. By the way I added four examples on scope if you are still confused – Muntasir Alam Aug 30 '16 at 17:44
  • I was assuming that doFoo worked as other objects and I could access the a variable inside it. If I declare a inside doFoo I was expecting 'this' to refer to that a, as doFoo is the call-side for foo. My english is not perfect, sorry. – Rrmm Aug 30 '16 at 17:45
  • I tend to misunderstand things in crazy/silly ways. I thought I would be able to access 'a' as a property of the function. I'm going to accept your answer as correct anyway. At least I identified the source of confusion. – Rrmm Aug 30 '16 at 17:52
  • Make sure you read @martriay's answer and mine as well, they might help you understand. – Muntasir Alam Aug 30 '16 at 17:56
0

Javascript has lexical scope, so in your example this always refers to the global version of a, which gets overwritten in the first snippet.

As var defines a new variable in that scope, you're not modifying the global one, therefore printing global in the second snippet.

martriay
  • 5,632
  • 3
  • 29
  • 39
0

First a is global, then we call doFoo, the global a is set to local.

We now call fn() which calls foo(), here this refers to the current execution context. Here this refers to the global scope.

Thus alerting local

Extra homework for you: Following similar logic, why does the following alert global?

var a = "global"

function thisA()
{
    var a = "local";
    fn();
}

function fn()
{
    alert(this.a);
}

thisA();

Examples on Scope

1.

var a = 3;
function myA()
{
    a = 2;
}

myA();
console.log(a); // 2

2.

var a = 3;
function myA()
{
    var a = 2;
}

myA();
console.log(a); // 3

3.

var a = 3;
function myA()
{
    var a = 2;
    myOtherA();
}

function myOtherA()
{
     a = 4;
}

myA();
console.log(a); // 4 since myOtherA() sets the global var a = 3 to 4, NOT myA();

4.

var a = 3;
function myA()
{
    var a = 2;
    function withinA()
    {
        a = 10;
    }
    withinA(); // changes var a = 2, to 10 NOT the outer a =3
}



myA();
console.log(a); // Still 3
Muntasir Alam
  • 1,777
  • 2
  • 17
  • 26