Skip to content

Commit af00a0d

Browse files
Basarat Ali SyedBasarat Ali Syed
Basarat Ali Syed
authored and
Basarat Ali Syed
committed
document closure. Closes basarat#139
1 parent bc4d1d0 commit af00a0d

File tree

5 files changed

+186
-1
lines changed

5 files changed

+186
-1
lines changed

SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* [Why TypeScript](docs/why-typescript.md)
55
* [JavaScript](docs/javascript/recap.md)
66
* [Awful](docs/javascript/awful.md)
7+
* [Closure](docs/javascript/closure.md)
78
* [Future JavaScript Now](docs/future-javascript.md)
89
* [Classes](docs/classes.md)
910
* [Classes Emit](docs/classes-emit.md)

code/javascript/closure.js

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
"use strict";
2+
function outerFunction(arg) {
3+
var variableInOuterFunction = arg;
4+
function bar() {
5+
console.log(variableInOuterFunction);
6+
}
7+
bar();
8+
}
9+
outerFunction("hello closure");
10+
var another;
11+
(function (another) {
12+
function outerFunction(arg) {
13+
var variableInOuterFunction = arg;
14+
return function () {
15+
console.log(variableInOuterFunction);
16+
};
17+
}
18+
var innerFunction = outerFunction("hello closure!");
19+
innerFunction();
20+
})(another = exports.another || (exports.another = {}));
21+
var revealing;
22+
(function (revealing) {
23+
function createCounter() {
24+
var val = 0;
25+
return {
26+
increment: function () { val++; },
27+
getVal: function () { return val; }
28+
};
29+
}
30+
var counter = createCounter();
31+
counter.increment();
32+
console.log(counter.getVal());
33+
})(revealing = exports.revealing || (exports.revealing = {}));
34+
var server;
35+
(function (server) {
36+
server.on(function handler(req, res) {
37+
loadData(req.id).then(function (data) {
38+
res.send(data);
39+
});
40+
});
41+
})(server = exports.server || (exports.server = {}));

code/javascript/closure.ts

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
function outerFunction(arg) {
2+
var variableInOuterFunction = arg;
3+
4+
function bar() {
5+
console.log(variableInOuterFunction); // Access a variable from the outer scope
6+
}
7+
8+
// Call the local function to demonstrate that it has access to arg
9+
bar();
10+
}
11+
12+
outerFunction("hello closure"); // logs hello closure!
13+
14+
15+
export namespace another {
16+
function outerFunction(arg) {
17+
var variableInOuterFunction = arg;
18+
return function() {
19+
console.log(variableInOuterFunction);
20+
}
21+
}
22+
23+
var innerFunction = outerFunction("hello closure!");
24+
25+
// Note the outerFunction has returned
26+
innerFunction(); // logs hello closure!
27+
}
28+
29+
30+
export namespace revealing {
31+
function createCounter() {
32+
let val = 0;
33+
return {
34+
increment() { val++ },
35+
getVal() { return val }
36+
}
37+
}
38+
39+
let counter = createCounter();
40+
counter.increment();
41+
console.log(counter.getVal()); // 1
42+
}
43+
44+
export namespace server {
45+
server.on(function handler(req, res) {
46+
loadData(req.id).then(function(data) {
47+
// the `res` has been closed over and is available
48+
res.send(data);
49+
})
50+
});
51+
}

code/javascript/tsconfig.json

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"compilerOptions": {
3+
"target": "es5",
4+
"module": "commonjs",
5+
"moduleResolution": "node",
6+
"isolatedModules": false,
7+
"jsx": "react",
8+
"experimentalDecorators": true,
9+
"emitDecoratorMetadata": true,
10+
"declaration": false,
11+
"noImplicitAny": false,
12+
"noImplicitUseStrict": false,
13+
"removeComments": true,
14+
"noLib": false,
15+
"preserveConstEnums": true,
16+
"suppressImplicitAnyIndexErrors": true
17+
},
18+
"exclude": [
19+
"node_modules",
20+
"typings/browser",
21+
"typings/browser.d.ts"
22+
],
23+
"compileOnSave": true,
24+
"buildOnSave": false,
25+
"atom": {
26+
"rewriteTsconfig": false
27+
}
28+
}

docs/javascript/closure.md

+65-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,67 @@
11
## Closure
22

3-
The best thing that JavaScript ever got was closures.
3+
The best thing that JavaScript ever got was closures. A function in JavaScript has access to any variables defined in the outer scope. Closures are best explained with examples:
4+
5+
```ts
6+
function outerFunction(arg) {
7+
var variableInOuterFunction = arg;
8+
9+
function bar() {
10+
console.log(variableInOuterFunction); // Access a variable from the outer scope
11+
}
12+
13+
// Call the local function to demonstrate that it has access to arg
14+
bar();
15+
}
16+
17+
outerFunction("hello closure"); // logs hello closure!
18+
```
19+
20+
You can see that the inner function has access to a variable (variableInOuterFunction) from the outer scope. The variables in the outer function have been closed by (or bound in) the inner function. Hence the term **closure**. The concept in itself is simple enough and pretty intuitive.
21+
22+
Now the awesome part: The inner function can access the variables from the outer scope *even after the outer function has returned*. This is because the variables are still bound in the inner function and not dependent on the outer function. Again let's look at an example:
23+
24+
```ts
25+
function outerFunction(arg) {
26+
var variableInOuterFunction = arg;
27+
return function() {
28+
console.log(variableInOuterFunction);
29+
}
30+
}
31+
32+
var innerFunction = outerFunction("hello closure!");
33+
34+
// Note the outerFunction has returned
35+
innerFunction(); // logs hello closure!
36+
```
37+
38+
### Reason why its awesome
39+
It allows you to compose objects easily e.g. the revealing module pattern:
40+
41+
```ts
42+
function createCounter() {
43+
let val = 0;
44+
return {
45+
increment() { val++ },
46+
getVal() { return val }
47+
}
48+
}
49+
50+
let counter = createCounter();
51+
counter.increment();
52+
console.log(counter.getVal()); // 1
53+
counter.increment();
54+
console.log(counter.getVal()); // 2
55+
```
56+
57+
At a high level it is also what makes something like nodejs possible (don't worry if it doesn't click in your brain right now. It will eventually 🌹):
58+
59+
```ts
60+
// Pseudo code to explain the concept
61+
server.on(function handler(req, res) {
62+
loadData(req.id).then(function(data) {
63+
// the `res` has been closed over and is available
64+
res.send(data);
65+
})
66+
});
67+
```

0 commit comments

Comments
 (0)