JavaScript 101-#22 – Scope, context and this

Variables are foundations of JavaScript and every other programming language. Without proper knowledge about them, you will not get any far. However, we already covered variables in one of previous posts. Today, we are going to focus on another subject closely related to variables and important as well. This subject is scope. In this post we are going to practice working with variables, functions and more in different scopes. Without further ado, let’s begin!

Note

In order to practice the code we will use today you don’t need any IDE installed on your computer (if you don’t have any). You can as well use some online options like Codepen.io, JSBin, JSFiddle or just pick the developer console in your browser. Also, don’t worry about HTML or CSS files, we are going to work only with JavaScript.

Scope

When it comes to scope, we have two choices. We can either work with global scope or local. That’s it. These are the only types available. What’s the difference? Anything (variable, function, object) defined in global scope is and will be accessible from any part of the program (script file). On the other hand, code defined in local scope (inside object, function or closure) can be accessed only in that particular scope. No code from the outside can work with it.

To imagine it better, let’s demonstrate it on couple examples. First, we will create few variables, functions and objects in global scope.

JavaScript:

// global scope
var scope = “global”;
var float = 3.14;
var boolean = false;
function say () { … };
var spencer = new Object();

All of the variables, function say and object spencer are defined in global scope, so you can work with them, manipulate them and also change them as you wish in any part of the script.

JavaScript:

// global scope
var scope = “global”;
var float = 3.14;
var boolean = false;
function say () {
 return scope;
};
var spencer = new Object();
spencer.favNumber = float;

console.log(say()); // “global”
console.log(spencer.favNumber); // 3.14
scope = “Still global?”; // value of the scope variable is now “Still global?”
console.log(jump()); // “Still global?”
boolean = true; // value of the boolean variable is now “true”

Now, let’s change the things a bit and move to local scope. We will take the variables defined in example above and wrap them inside new object. So, from now these variables will be defined in local scope – scope of the object – and they will be accessible only inside the object or through it using dot notation.

JavaScript:

var variables = {
 scope: “local”,
 float: 3.14,
 boolean: false,
 say: function() {
 return this.scope;
 },
 spencer: new Object()
}

spencer.favNumber = float; // error – spencer is not defined
console.log(spencer.favNumber); // error – spencer is not defined
console.log(say()); // - error – say is not defined

As you can see, any time when you try to access some code created inside the variable object, you will get an error. Outside this object, none of the variables, function or object (spencer) exist. Therefore, when we try to change the value of scope outside the object where it is defined, it will create new variable called scope in global scope while keeping the original one untouched.

JavaScript:

var variables = {
 scope: “local”,
 float: 3.14,
 boolean: false,
 say: function() {
 return this.scope;
 },
 spencer: new Object()
}

scope = "Still local?"; // creates new variable
console.log(scope); // "Still local?" (new variable)
console.log(variables.scope); // “local” (variable created in “variables” object)

This is great way to protect your code from being overwritten. Another benefit of using local scope is in terms of performance. Since we created all the variables into object, they don’t exist and so they have no influence on browser’s cache. Browser will create them only if we access the object variable or some variable inside using dot notation.

JavaScript:

var variables = {
 scope: “local”,
 float: 3.14,
 boolean: false,
 say: function() {
 return this.scope;
 },
 spencer: new Object()
}

console.log(variables.scope); // “local”
console.log(variables.float); // 3.14
console.log(variables.boolean); // false
console.log(variables.say()); // “local”
console.log(variables.spencer); // [object Object] { … }

Context & this

You might notic the this keyword inside the say function. By using this we are working in the context of variables object and so we reference to scope variable inside this object. What if we add new global variable scope and create new function referencing to the scope without this keyword?

JavaScript:

var variables = {
 scope: “local”,
 float: 3.14,
 boolean: false,
 say: function() {
 return this.scope;
 },
 // new function without “this” keyword
 check: function() {
 return scope;
 },
 spencer: new Object()
}

// new scope
var scope = “I'm global!”;
console.log(variables.say()); // “local”
console.log(variables.check()); // “I'm global!”

See? When we omitted this keyword in check function, the context has changed as well. The scope variable now refers to scope variable created in global scope. If we remove the scope variable in global scope, the check function will return error – scope is not defined.

When we are talking about this and context, let’s take a detailed look at how they work. To understand it completely, we are going to create another object joshua. Both, spencer and joshua, will have firstName, lastName and age variable, but spencer will also have greet function with message that will use this to include his name and age in it. Later on, we will create new function greetStolen for joshua and reference it to greeting inside spencer object.

JavaScript:

// object spencer
var spencer = {
 firstName: “Spencer”,
 lastName: “Crowly”,
 age: 25,
 greeting: function() {
 console.log(“Hi, my name is “ + this.firstName + “ “ + this.lastName + “ and I am “ + this.age + “ years old.”);
 }
};

spencer.greeting(); // “Hi, my name is Spencer Crowly and I am 25 years old.”

// new object joshua
var joshua = {
 firstName: “Joshua”,
 lastName: “Sick”,
 age: 19
};

// attaching greeting function to joshua
joshua.greetStolen = spencer.greeting;

// calling the greetStolen function
joshua.greetStolen(); // “Hi, my name is Joshua Sick and I am 19 years old.”

Did you expect this? If not, trust me, there is no magic or dark secret. As said above, this always reference to local context – context of the object it is used in. So, even if we steal the greet function for spencer and attach it to joshua, this included inside the function will do what it should – reference to local context -> joshua object. Remember every time you use this inside some object, it will always reference to data inside that object.

Summary

Well, this is all. I hope that this post will help you understand the difference between local and global scope and how context and this keyword work. If you have any questions about this or any other topic, leave a comment or write me a message. I’m here to help you. Thank you for your time.

Do you have any questions, recommendations, thoughts, advice or tip you would like to share with other readers of this blog, and me? Please share it in a comment. You can also send me a mail. I would love to hear from you.

Did you like this article? Please subscribe.

Are you on social media? Let's connect! You can find me on Twitter, GitHub and Dribbble.

Alex Devero

I'm Founder/CEO of DEVERO Corporation. Entrepreneur, designer, developer. My mission and MTP is to accelerate the development of humankind through technology.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.