19-09-2019
Javascript - Scope
Ik zie, ik zie, wat jij niet ziet.
In javascript bepaald "scope" of bepaalde variabelen te gebruiken / zichtbaar zijn of niet. Ook bepalen ze hoe lang een variabele in het geheugen blijft hangen voordat de variabele eruit gegooid wordt door javascript's garbage collection. Eerst had je global en function / local scope. Tegenwoordig ook module en block scope. Laten we ze stap voor stap bekijken.
Local scope
Local scope is onderverdeeld in twee soorten. Namelijk function en block scope. Eerst hadden we alleen function scope. Maar sinds ES6 hebben we ook block scope.
Function scope
Als je een nieuwe functie maakt, word er ook een function scope gemaakt. Alles wat je tussen de accolades van die function tikt, blijft in die functie, en is daarbuiten niet beschikbaar. What happens in the function stays in the function. Tenzij je speciale dingen doet, maar daar gaan we nu niet op in. Het maakt tevens niet uit of je de function hebt aangeroepen of niet. Voorbeeld:
function fooFunction() {
let message = 'Je ziet me van buiten deze functie lekker toch niet!';
//Hier kan ik message gebruiken
}
//Hier kan ik message niet gebruiken
Block scope
In javascript kun je code groeperen in blocks. Een block bestaat simpelweg uit twee accolades. Meer is het niet. Doorgaans gebruik je ze niet zoals hier beneden, maar gebruik je ze in combinatie met een if, switch, else, for enzovoorts. Zo'n block heeft zijn eigen scope, namelijk de block scope.
{
//Hier bevind zich de block scope
}
//En hier de global scope
if(name = 'test')
{
//Hier bevind zich een tweede block scope
}
//En hier nog altijd de global scope.
Hoe de scope werkt voor je variabelen is afhankelijk hoe je die definieert. Als je een variabele definieert met let of const is deze alleen te gebruiken / zichtbaar tussen de accolades. Daarbuiten niet:
{
const gender = 'male';
let age = 21;
console.log(gender+' '+age); //Logt: male 21
}
console.log(gender); //Logt niets. Veroorzaakt error: gender is not defined
Gebruik je var. Dan werkt het ineens heel anders, en moet je goed opletten wat je doet! Var is namelijk niet "block scoped" maar "function scoped" of "global scoped". Dit betekent dat een variabele in een block, daarbuiten ook beschikbaar is. Maar niet buiten de omliggende functie. Is er geen omliggende functie, dan is de variabele globaal beschikbaar. Gebruik je var. Dan werkt het ineens heel anders, en moet je goed opletten wat je doet! Var is namelijk niet "block scoped" maar "function scoped" of "global scoped". Dit betekend dat een variabele in een block, daarbuiten ook beschikbaar is. Maar niet buiten de omliggende functie. Is er geen omliggende functie, dan is de variabele globaal beschikbaar:
Type var global scoped
if(2 !== 1)
{
const gender = 'male';
let age = 21;
var type = 'person';
console.log(gender+' '+age);
}
console.log(type); //Logt person
console.log(age); //Logt niets. Veroorzaakt deze fout: age is not defined
Type var function scoped
function testFunction() {
if (2 !== 1) {
const gender = 'male';
let age = 21;
var type = 'person'; //Type is alleen maar beschikbaar in testFunction. Ook buiten de if block.
}
}
console.log(type); //Logt niets, verzoorzaakt error type is not defined.
Module scope
Stel je hebt een bestand met de naam logger.js. En dit heeft een ES6 / ES2015 module. Een logger. Module scope, betekent dat alles wat je in het bestand logger.js, alleen maar in dat bestand kan gebruiken. Tenzij je het exporteert en ergens anders importeert. In het voorbeeld hier beneden zal de variabele someSettings niet beschikbaar zijn in andere bestanden. Maar logger wel, als deze geïmporteerd is.
class Logger {
//Logger class implementatie
}
let someSettings = ['nice', 'settings'];
export { Logger }
Global scope
Global scope is de scope die gebruikt word als je je variabele niet definieert in een module, functie, of block scope als let of const. Met global scope, bedoelen we in de browser het window object. Het window object heeft tevens een window object, maar dat verwijst naar zichzelf. In node omgevingen is diezelfde scope zoals de module scope in een browser. Dus lokaal aan de module zelf.
window.window === window //true