(click anywhere to close)
OPEN MENU

[JavaScript] Scope

category: Website | course: JavaScript | difficulty:

I brought you the wonderful news that you could access variables from anywhere. Well, I lied.

JavaScript uses something called function scope, which means that variables declared inside functions have local scope. Variables declared anywhere else have global scope. In both cases, however, you still need to declare a variable before you’re able to access it.

Global scope variables can be accessed from anywhere. Local scope variables disappear as soon as the function is done executing, and can’t be accessed from anywhere outside of it.

Scope is the set of variables, objects and functions you have access to in a certain code block

It’s recommended to keep your variables local as much as possible. This prevents name collisions, and is faster to execute. Why? Because, when JavaScript encounters a variable name, it starts looking at the function that contains this piece of code. If it can't find the variable declaration there, it looks at the function or code block that contains it, one level up the hierarchy. It keeps moving levels upwards, until it reaches the point where the variable is declared. The more local your variables, the shorter you keep this lookup distance, and the faster it will execute.

If it doesn’t find the variable declaration, it will just assume the variable to be global. This means that you can declare global variables everywhere by not using the var keyword, but I don’t recommend doing this very often. This also means that you can access variables that haven’t been declared yet, which is called variable hoisting, and should be ignored as well.

The let Keyword

Sometimes, function scope isn’t what you want, but block scope is: variables declared inside a code block, have local scope with respect to that. In practice, this means that a variable declared between two braces ( { } ), doesn’t exist anywhere outside of these. To make a variable block scope, we don’t use the var keyword, but the let keyword.

if(true) {
	let x = 5;
}
console.log(x); //Prints undefined

The this Keyword

The keyword this refers to the current scope. More specifically, it returns the Object that owns the scope you’re in. If you’re in global scope, it returns the Global Object, which is the browser window. If you’re in a function, it returns whatever object called the function. The value of this is automatically kept track of by JavaScript, which is often what you want, but you can override it when calling functions.

The methods

call(thisObject, argument1, …, argumentn)
apply(thisObject, arguments)

both call the function they are attached to, and use thisObject as the value for this within the function. The only difference is that the second one allows you to pass in the arguments as one array, while the first one requires all arguments be listed explicitly.

function someFunc() {
	return this.a;
}

console.log( someFunc.apply({a:10}) ); //Prints 10
console.log( someFunc() ); //Prints undefined, because the root this object doesn't have a property a to access

Within block scope, you can simply save the object you want to perform the function of this in another variable, and use that.

var that = this;
// Somehow, the value of this is changed within this block
someBlock {
	//But luckily, we can just access the root this here with the that variable
	that.doSomething();
}

Closures

Because of this scoping mechanic, JavaScript has a feature called closures, which is a fancy name for something very simple. Say you have a function B nested inside another function A. Then B has access to everything inside of A, but A does not have access to whatever’s inside of B. If you let A return the function B, the latter will contain a reference to its environment at the moment function A was called. This allows you to work with variables that are untouchable from the outside, which is good for security and performance reasons.

/*
Subtract returns another function
The subtract function is only run once, initalizing the counter variable.
But, the function it returns, has a memory of its environment on creation, 
which enables it to subtract 2 from the running counter, instead of resetting it and subtracting from 100 every time.
*/

var subtract = (function () {
    var counter = 100;
    return function () {
    	return counter -= 2;
    }
})();

subtract();
subtract();
console.log(subtract()); //Prints 94
CONTINUE WITH THIS COURSE
Do you like my tutorials?
To keep this site running, donate some motivational food!
Crisps
(€2.00)
Chocolate Milk
(€3.50)
Pizza
(€5.00)