Javascript scope and context

Introduction

The scope and context of javascript maybe the most bizarre point when learning javascript, for people who learn programming from C/C++/JAVA those traditional language will find the concept of scope and context are particularly difficult to understand. However, it’s essential for a javascript developer to understand these.

Global scope

When you starting write a javascript, there is a default global scope called Window. Have a look at the image below

global

When a variable is in global scope it can be access by any other scope

var name = "Albert Einstein";

console.log("1: ", name)
function print(){
    console.log("2: ",name);
    (function inner(){
        console.log("3: ", name);
        function inner2(){
            console.log("4: ", name);
        }
        inner2();
    })();
}

print();
## 1:  Albert Einstein
## 2:  Albert Einstein
## 3:  Albert Einstein
## 4:  Albert Einstein

As you can see above, it prints four names. the first print is in the global scope, the second print is in the print function scope and so for print 3 and print 4.

let vs var

Let’s discuss local scope or function scope, as we mentioned above, global scope can be accessed everywhere, but local scope can only be accessed locally. In ECMAScript 6, there are two keywords introduced. Which will make the variable defined locally. let is just like var with local scope restriction and as the name shows const is a constant with local scope, when you try to modify a constant variable the interpret will yelling.

if(1){
// global scope
var name = "Albert Einstein";
// local scope
let age = 140;
// local scope
const occupation = "scientist";
}
console.log(name); // can be accessed
console.log(age); // cannot be accessed
console.log(occupation); // cannot be accessed

Context

When we talking about context, we are referring this keyword. Here is a definition from MDN [1]. > In most cases, the value of this is determined by how a function is called

So, what we have to find is who called this function. If a object called a function then this is the object, if a button is called the function, then this is the button. Let’s see several examples

calling from window

console.log(this); // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}

calling from an object

var obj = {
    func: function(){
        return this;
    }
};

console.log(obj.func());// return an object {}

strict mode if we don’t defind use strict in the beginning of a javascript document. this keyword will be default set to window in browser and global in nodejs.

without strict mode set

function foo(){
  return this;
}
foo() === window; // true

setup strict mode

function boo(){
  'use strict';
  return this;
}
boo() === undefined; // true

It’s always a good practice to set the strict mode

Apply, Call, Bind

These three functions are quite useful, apply and call are similar. bind is used to bind a function to another context. Here is an example showing that how people can change the context to make the calling more dynamic

var test = {
  prop: 42,
  func: function() {
    return this.prop;
  },
};

var test2 = {
  prop: 'Albert Einstein'
}

console.log(test.func()); // print 42
console.log(test.func.call(test2)); // print Albert Einstein

like a magic right? Here is the different use of apply, call and bind

func.call(context, "arg1", "arg2", "argn");
func.apply(context, ["arg1", "arg2", "argn"]);
func.bind(context);

call has slighly faster in performance than apply [2]

Public and Private

The function scope can be used to mimic traditional OOP language properties like private variables. Moreover, it can be used to manage namespace.

// only expose AwesomeModule keyword globally
var AwesomeModule = (function(){
  // private variable and methods
  let property = "property";
  
  function privateFunc(){
    ...
  }
  
  // you can access the method by AwesomeModule.publicFunc()
  // this kind format more like OOP 
  return {
    publicFunc: function(){
      // can access property and privateFunc()
    }
  }
})()

the code above has a small bizarre format (function() {})(). This is called immediately invoked function expression (IIFE). How to interpret this code? It’s simple, you define a function like this function(){}, you want to invoke it after define it the you just add an parenthesis (). However, in order to define this function you have to use another parenthesis enclose them, that’s all.

Closure

Closure is quite useful, like another magic in javascript. We know when a function return the variables define in that scope will be destroied or collected, but closure is not working that way, even the function returned, closure can still keep the variable. Let’s see an example

function outer(outerArg){
    let property = "property";
    return function(innerArg){
        console.log(outerArg);  
        console.log(property);  
        console.log(innerArg);  
    };
}
// notice outer has returned, property should be destroied
// but closure not working that way
var func = outer("from outer function");
// what we returned is not a variable is a function, we have to invoke the function
func("from inner function");

// output
// from outer function
// property
// from inner function

The example above shows that closure can not only access its own arguments, but the arguments from its outer functions and the returned function will not be invoked immediately, you can invoke the returned function whenever you want. Which is really handy. There is a very good visualization tool created by Tyler McGinnis. Which gives a really concrete example of what closure is [1]

References

1. The Ultimate Guide to Hoisting, Scopes, and Closures in JavaScript [Internet].TylerMcGinnis.com2019;Available from: https://tylermcginnis.com/ultimate-guide-to-execution-contexts-hoisting-scopes-and-closures-in-javascript

2. Understanding Scope in JavaScript [Internet].
Ahmed H.
Scotch2019;Available from: https://scotch.io/tutorials/understanding-scope-in-javascript

Avatar
Terry Pan
Student of Data Science

My research interests include Machine Learning, Data Science, Information Security and Software Engineering. I like to think like a engineer to tackle real world problems.

Related

comments powered by Disqus