During a Javascript tutorial at the Women Who Code LA Meetup, someone asked how to refer to a global variable from inside a function when the function has a local variable with the same name as the global variable.

Suggestion 1: ‘this’

Some online posts suggest using ‘this’ to access a global variable when there’s a local variable with the same name.


var a = 'global context';

function test() {
  var a = 'local context';

  console.log('local a: ', a);
  console.log('this a: ', this.a);
}

test();

// local a:  local context
// this a:  global context

‘this.a’ accesses the global variable, ‘a’ accesses the local variable. That’s exactly what we wanted. Everything is great, right?

Nope!

There are multiple ways to invoke a function in Javascript. The most common way is just to call the function, e.g. test(). Another way to invoke a function is with call or apply. When we use call or apply, we can pass in an object.

Look what happens when we invoke test using call.


var a = 'global context';

function test() {
  var a = 'local context';

  console.log('local a: ', a);
  console.log('this a: ', this.a);
}

 var testObject = {
   a: 'object context'
 }

test.call(testObject);

// local a:  local context
// this a:  object context

Unlike the first example, ‘this.a’ now refers the object context instead of the global context.

Why?!

For test(), ‘this.a’ returns ‘global context’. When a function is invoked by itself, ‘this’ refers to the global context.

For test.call(object), ‘this.a’ returns ‘object context’. When a function is invoked with call, ‘this’ refers to the context of the object that is passed in.

A third way to invoke a function is a method call.


var a = 'global context';

 var testObject = {
   a: 'object context',
   test: function() { 
        var a = 'local context';

        console.log('local a:', a)
        console.log('this.a:', this.a)
      }
 }

testObject.test();

// local a: local context 
// this.a: object context 

For testObject.test(), ‘this.a’ returns ‘object context’. When a function is invoked as a method of an object, ‘this’ refers to the object that the method belongs to.

We are using the exact same code for the test function, but depending on how test is invoked, ‘this.a’ can refer to either the global context or the object context.

Please don’t use ‘this’ to refer to a global variable inside a function.

Suggestion 2: window

Some online posts suggest using ‘window’ to access a global variable when there’s a local variable with the same name.


var a = 'global context';

function test() {
  var a = 'local context';

  console.log('local a: ', a);
  console.log('window a: ', window.a);
}

test();

// local a:  local context
// window a:  global context

‘window.a’ accesses the global variable, ‘a’ accesses the local variable. That’s exactly what we wanted. Everything is great, right?

Again, nope!

window.a works if you run the function in the browser, but what if you run the function in an environment that doesn’t have a browser?


// runs code on Node server

var a = 'global context';

function test() {
  var a = 'local context';

  console.log('local a: ', a);
  console.log('window a: ', window.a);
}

test();

// local a:  local context
// ReferenceError: window is not defined

Node server doesn’t have a window, so you end up with an error when you use ‘window.a’.

Please don’t use ‘window’ to refer to a global variable inside a function.

Conclusion

So back to the original question: how do we refer to a global variable from inside a function when the function has a local variable with the same name as the global variable?

Simple recommendation: Don’t do it!

Because there are multiple ways to invoke functions (test(), test.call(), testObject.test()) and multiple environments to run Javascript (browser, server, etc.), there is no consistent way to refer to the global variable when there is local variable with the same name.

If you need to refer to the global variable, then don’t redeclare the variable inside the function. Give the variable inside the function a different name.


var a = 'global context';

function test() {
  var b = 'local context';

  console.log('a: ', a);
  console.log('b: ', b);
}

test();

//  a:  global context
//  b:  local context

That’s a whole lot of words for a simple ‘no’ answer. I hope this post either clears things up about how Javascript works or makes you more confused about how Javascript works.