When I started with JavaScript, most of my coding experience came from PHP, C and Java. So when I saw the first snippets of JavaScript, it looked like Voodoo to me. Functions defined here and there, put into variables, moved around and they even used variables that didn't seem to belong to them.
Who calls these functions?
Where do they get their variables from?
I don't even...
Introducing Closures
So you probably read about closures are a thing in JavaScript. Well, they are probably the main thing.
First: Functions
So what is needed to understand them?
You are probably used to simple static(?) function definitions from other languages. They exist in JS too.
function f(x) {
return x + 10;
}
f(10); // -> 20
But there are also function expressions.
An expression is a language construct that (kinda) return something, you say they evaluate to something. if
or for
, for example aren't expressions, you cant write let x = if (b > 10) ...
. A function call, a calculation or a comparison are expressions.
f(10); // returns something -> 20
10 * 3; // evaluates to 30
10 === 3; // evaluates to false
In JS not only function calls, but also their definitions can be expressions.
let f = function myFunction() {}; // evaluates to a reference to the function myFunction
let g = function () {}; // The function doesn't even have to have a name
// because we can call it via its reference stored in g
g();
This allows us to define functions somewhere save, store it in a variable and send it around our application, for example if you want to use it as a callback.
let f = function () {}; // store function reference
window.addEventListener("load", f); // call it when something happens
As you know from other languages, there are global and local variables.
x = 20;
function f(y) {
let z = 10;
return x * y * z;
}
In the example x
is defined without var
, let
or const
so it will become a global variable. In JS this means it will be attached to the global window
object in browsers. Global variables can be accessed anywhere, for any function, so we can use it inside f()
.
Second: Closures
What has this to do with closures?
Well closures are functions that close over or capture their definition context. Which sounds kinda cryptic, but means something like, they can use the variables that are defined around them.
It's a bit like globals.
x = 10; // global
function f() { // -- definition context of g
let y = 20; // local to f, but g has access
let g = function (z) {
return x * y * z; // global * context * local
}
return g;
} // -- end of g's def. context
function h(a) {
return x * a; // no access to y, just global and local
}
let newG = f();
newG(2);
`
Why would you use this? For callbacks, for example.
Imagine you want to access some non-global data, but the functions you pass as callbacks won't receive this data.
`javascript
let user = {name: "kay-is"};
// the function passed to setTimeout won't get any arguments
// but it has access to the variables "around" its definition
setTimeout(function (alwaysUndefined) {
alert(user.name) // alert is global
// user is local to the parent scope
}, 100)
`
Or imagine, you have some data, that shouldn't be modified.
`javascript
function ReadOnly(user) {
// the parameter is local to ReadOnly
// getName and getAge are closures that can access them
return {
getName: function() { return user.name; },
getAge: function () { return user.age; }
}
}
// somewhere save
let peter = {name: "Peter", age: 43}
let readOnlyPeter = ReadOnly(peter);
// code with access to peter can modify the object
// code with access to readOnlyPeter can't modify it
readOnlyPeter.getName();
readOnlyPeter.getAge();
readOnlyPeter.name = "Franz"; // readOnlyPeter doesn't have this attribute.
`
Conclusion
Closures could be called the bread and butter of JavaScript. JavaScript is an event based system where almost everything is handled asynchronously by callbacks, even promises or observables are just abstractions over this fact.
They allow to write code without the need of globals, but still maintain a bit of the light-weight feeling globals bring to programming.
Top comments (0)