Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions bin/scope-chains-closures
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env node

require('../index.js').execute(process.argv.slice(2));
File renamed without changes.
File renamed without changes.
21 changes: 5 additions & 16 deletions exercises/closures/problem.md → exercises/closures/en/problem.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
# Closures

Closures are an important part of the Javascript language. They are what enables
the callback-last programming most prominent in node, and provide an excellent
mechanism for handling the asynchronous nature of most Javascript tasks.
Closures are an important part of the Javascript language. They are what enables the callback-last programming most prominent in node, and provide an excellent mechanism for handling the asynchronous nature of most Javascript tasks.

To properly understand closures, let's start with an example scope chain:

Expand All @@ -25,9 +21,7 @@ someFunc()
```

Given how nesting scope works, it's possible for an inner scope within
`someFunc()` to access `bar`. In this example, let's say `inner()` accesses
`bar`:
Given how nesting scope works, it's possible for an inner scope within `someFunc()` to access `bar`. In this example, let's say `inner()` accesses `bar`:

```
someFunc()
Expand All @@ -42,17 +36,12 @@ alert(bar)

Then `inner()` is said to _Close Over_ `bar`. Therefore `inner()` is a _Closure_.

To power the callback style of programming, the closure will be maintained even
if `inner()` isn't executed immediately. It is perfectly legal in Javascript to
pass `inner` around / return it from `someFunc()` for later execution. All the
while, `bar` will continue to be available.
To power the callback style of programming, the closure will be maintained even if `inner()` isn't executed immediately. It is perfectly legal in Javascript to pass `inner` around / return it from `someFunc()` for later execution. All the while, `bar` will continue to be available.

----

# Your Mission

Modify your solution from the previous lesson to set `bar = true` inside `zip()`,
then return the function `zip` as the result of `foo()`
Modify your solution from the previous lesson to set `bar = true` inside `zip()`, then return the function `zip` as the result of `foo()`

Once complete, execute `$ADVENTURE_COMMAND verify <your-file.js>` to verify your
solution.
Once complete, execute `$ADVENTURE_COMMAND verify <your-file.js>` to verify your solution.
File renamed without changes.
12 changes: 12 additions & 0 deletions exercises/closures/ja/fail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Almost there!

Check the errors above to see where you went wrong.

# Hints

* The task is to return the function `zip`, not the result of `zip()`.
* The value you set to `bar` isn't important.

# More Help

* If you're still having troubles, post a question in the nodeschool issues repository: http://bit.ly/scope-chains-question
4 changes: 4 additions & 0 deletions exercises/closures/ja/pass.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Success!

Awesome stuff - you closed over the variable `bar` inside `zip`, then returned
`zip`.
47 changes: 47 additions & 0 deletions exercises/closures/ja/problem.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
Closures are an important part of the Javascript language. They are what enables the callback-last programming most prominent in node, and provide an excellent mechanism for handling the asynchronous nature of most Javascript tasks.

To properly understand closures, let's start with an example scope chain:

```
someFunc()
|
inner()
|
foo()
```

Let's say `someFunc()` declares a variable `bar`:

```
someFunc()
var bar
```

Given how nesting scope works, it's possible for an inner scope within `someFunc()` to access `bar`. In this example, let's say `inner()` accesses `bar`:

```
someFunc()
var bar
|
inner()
alert(bar)
```

Then `inner()` is said to _Close Over_ `bar`. Therefore `inner()` is a _Closure_.

To power the callback style of programming, the closure will be maintained even if `inner()` isn't executed immediately. It is perfectly legal in Javascript to pass `inner` around / return it from `someFunc()` for later execution. All the while, `bar` will continue to be available.

----

# Your Mission

Modify your solution from the previous lesson to set `bar = true` inside `zip()`, then return the function `zip` as the result of `foo()`

Once complete, execute `$ADVENTURE_COMMAND verify <your-file.js>` to verify your solution.
27 changes: 27 additions & 0 deletions exercises/closures/ja/solution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
----

# Solution

Let's look at the scope chain for your solution:

```
foo()
var bar
return zip
|
zip()
bar = true
```

By referencing `bar` within `zip`, we have created a _Closure_ where `zip()` _closes over_ the variable `bar` from its parent scope `foo()`.

Since we are returning the function `zip`, the reference to `bar` is maintained (and hence the closure is maintained) until `zip` is no longer required.

This has interesting implications for memory, which we will cover in the next lesson.

----

# Next lesson

Execute `$ADVENTURE_COMMAND` to move on to the next lesson: _Garbage Collection_.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Unknown error..?

Congratulations! If you've made it to this screen, you deserve a nyan cat as a
reward :D
Congratulations! If you've made it to this screen, you deserve a nyan cat as a reward :D

░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄░░░░░░░░░
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
# Garbage Collection
Memory in Javascript is managed automatically by the runtime. The runtime decides when/if to release any allocated memory. This decision process is called _Garbage Collection_.

Memory in Javascript is managed automatically by the runtime. The runtime
decides when/if to release any allocated memory. This decision process is called
_Garbage Collection_.

Every javascript runtime has their own algorithm for garbage collection, but
most use a variation of Mark & Sweep. The Mark & Sweep algorithm works by
marking references to memory (variables, functions, etc) which are still
reachable from active code. Any reference which is not marked, is swept into
the garbage (i.e. the memory is freed).
Every javascript runtime has their own algorithm for garbage collection, but most use a variation of Mark & Sweep. The Mark & Sweep algorithm works by marking references to memory (variables, functions, etc) which are still reachable from active code. Any reference which is not marked, is swept into the garbage (i.e. the memory is freed).

This concept of marking reachable memory is particulary relevant to closures:

Expand All @@ -24,29 +16,19 @@ return inner
```

When the closure `inner()` is returned from `someFunc()`, it maintains its
reference to `bar`. The Mark & Sweep algorithm will mark `bar` as reachable, and
hence will _not_ garbage collect it.
When the closure `inner()` is returned from `someFunc()`, it maintains its reference to `bar`. The Mark & Sweep algorithm will mark `bar` as reachable, and hence will _not_ garbage collect it.

For `inner()` to correctly resolve its reference to `bar`, not only does the
memory for `bar` need to be kept, but the scope chain which describes how to
reach `bar` must also be kept.
For `inner()` to correctly resolve its reference to `bar`, not only does the memory for `bar` need to be kept, but the scope chain which describes how to reach `bar` must also be kept.

Once the reference to `inner()` is no longer required, it can be marked for
garbage collection, which in turn means `bar` can also be marked, and finally
the entire scope chain can be marked, resulting in the freeing of all the
memory.
Once the reference to `inner()` is no longer required, it can be marked for garbage collection, which in turn means `bar` can also be marked, and finally the entire scope chain can be marked, resulting in the freeing of all the memory.

In this way, Scope, Scope Chains, Closures, and Garbage Collection are all
closely related.
In this way, Scope, Scope Chains, Closures, and Garbage Collection are all closely related.

----

# Your Mission

In this challenge, you will be required to use Chrome DevTools for detecting
Garbage Collection events. Follow these steps to get a feel for what happens
when Chrome performs its Mark & Sweep algorithm:
In this challenge, you will be required to use Chrome DevTools for detecting Garbage Collection events. Follow these steps to get a feel for what happens when Chrome performs its Mark & Sweep algorithm:

1) Fire up a new tab in Chrome
2) Open the DevTools > Timeline tab
Expand All @@ -65,12 +47,6 @@ when Chrome performs its Mark & Sweep algorithm:
11) Clicking this event will reveal information about total memory garbage
collected, and how long it took.

One particularly interesting thing of note here is the length of time Garbage
Collection can take: Often well beyond the 16ms maximum required to keep it
within a single frame (at 60fps). While garbage collection occurs, it blocks the
main thread, which means other Javascript cannot be executed until the event
completes. Be conscious of how janky your application may become due to
extensive Garbage Collection events!
One particularly interesting thing of note here is the length of time Garbage Collection can take: Often well beyond the 16ms maximum required to keep it within a single frame (at 60fps). While garbage collection occurs, it blocks the main thread, which means other Javascript cannot be executed until the event completes. Be conscious of how janky your application may become due to extensive Garbage Collection events!

**Note**: If you'd like to get that lovely `[COMPLETED]` label for this lesson,
Run `$ADVENTURE_COMMAND verify`
**Note**: If you'd like to get that lovely `[COMPLETED]` label for this lesson, Run `$ADVENTURE_COMMAND verify`
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@

# Congratulations!

Now that you know all about Scope Chains, Closures, & Garbage Collection, why
not tweet about it: `http://bit.ly/sccjs-twitter-share`
Now that you know all about Scope Chains, Closures, & Garbage Collection, why not tweet about it: `http://bit.ly/sccjs-twitter-share`
1 change: 0 additions & 1 deletion exercises/garbage-collection/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
var problem = require('../../problem');

module.exports = {
title: 'Garbage Collection',
problem: problem(__dirname, function (args, t) {
t.end();
})
Expand Down
18 changes: 18 additions & 0 deletions exercises/garbage-collection/ja/fail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Unknown error..?

Congratulations! If you've made it to this screen, you deserve a nyan cat as a reward :D

░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄░░░░░░░░░
░░░░░░░░▄▀░░░░░░░░░░░░▄░░░░░░░▀▄░░░░░░░
░░░░░░░░█░░▄░░░░▄░░░░░░░░░░░░░░█░░░░░░░
░░░░░░░░█░░░░░░░░░░░░▄█▄▄░░▄░░░█░▄▄▄░░░
░▄▄▄▄▄░░█░░░░░░▀░░░░▀█░░▀▄░░░░░█▀▀░██░░
░██▄▀██▄█░░░▄░░░░░░░██░░░░▀▀▀▀▀░░░░██░░
░░▀██▄▀██░░░░░░░░▀░██▀░░░░░░░░░░░░░▀██░
░░░░▀████░▀░░░░▄░░░██░░░▄█░░░░▄░▄█░░██░
░░░░░░░▀█░░░░▄░░░░░██░░░░▄░░░▄░░▄░░░██░
░░░░░░░▄█▄░░░░░░░░░░░▀▄░░▀▀▀▀▀▀▀▀░░▄▀░░
░░░░░░█▀▀█████████▀▀▀▀████████████▀░░░░
░░░░░░████▀░░███▀░░░░░░▀███░░▀██▀░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
1 change: 1 addition & 0 deletions exercises/garbage-collection/ja/pass.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Everything Looks Good Here...
52 changes: 52 additions & 0 deletions exercises/garbage-collection/ja/problem.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
Memory in Javascript is managed automatically by the runtime. The runtime decides when/if to release any allocated memory. This decision process is called _Garbage Collection_.

Every javascript runtime has their own algorithm for garbage collection, but most use a variation of Mark & Sweep. The Mark & Sweep algorithm works by marking references to memory (variables, functions, etc) which are still reachable from active code. Any reference which is not marked, is swept into the garbage (i.e. the memory is freed).

This concept of marking reachable memory is particulary relevant to closures:

```
someFunc()
var bar
return inner
|
inner()
alert(bar)
```

When the closure `inner()` is returned from `someFunc()`, it maintains its reference to `bar`. The Mark & Sweep algorithm will mark `bar` as reachable, and hence will _not_ garbage collect it.

For `inner()` to correctly resolve its reference to `bar`, not only does the memory for `bar` need to be kept, but the scope chain which describes how to reach `bar` must also be kept.

Once the reference to `inner()` is no longer required, it can be marked for garbage collection, which in turn means `bar` can also be marked, and finally the entire scope chain can be marked, resulting in the freeing of all the memory.

In this way, Scope, Scope Chains, Closures, and Garbage Collection are all closely related.

----

# Your Mission

In this challenge, you will be required to use Chrome DevTools for detecting Garbage Collection events. Follow these steps to get a feel for what happens when Chrome performs its Mark & Sweep algorithm:

1) Fire up a new tab in Chrome
2) Open the DevTools > Timeline tab
3) Ensure the settings are like so: `http://i.imgur.com/RMovIw4.png`
a) Frames View is unselected (allows seeing memory graphs)
b) Flame Chart View is selected (allows seeing where execution time is spent)
c) Only "Memory" is selected from the options
4) Click the solid gray record button to begin capturing data
5) Visit `http://www.stackoverflow.com` (or your favourite website)
6) Click the now-red record button to stop capturing data
7) You should now see something similar to: `http://i.imgur.com/ZCNMrI1.png`
8) The part we're interested in is when memory suddenly drops:
`http://i.imgur.com/FyMyRVI.png`
9) Click this drop in memory to select it
10) Now look for the yellow event called "GC Event": `http://i.imgur.com/3ieSxIZ.png`
11) Clicking this event will reveal information about total memory garbage
collected, and how long it took.

One particularly interesting thing of note here is the length of time Garbage Collection can take: Often well beyond the 16ms maximum required to keep it within a single frame (at 60fps). While garbage collection occurs, it blocks the main thread, which means other Javascript cannot be executed until the event completes. Be conscious of how janky your application may become due to extensive Garbage Collection events!

**Note**: If you'd like to get that lovely `[COMPLETED]` label for this lesson, Run `$ADVENTURE_COMMAND verify`
5 changes: 5 additions & 0 deletions exercises/garbage-collection/ja/solution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
----

# Congratulations!

Now that you know all about Scope Chains, Closures, & Garbage Collection, why not tweet about it: `http://bit.ly/sccjs-twitter-share`
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# Global Scope & Shadowing

## Global Scope

Understanding where Scope Chains end is an important part of scoping. All
Javascript runtimes must implicitly create a _Global Scope_ object (`window` in
the browser, `global` in node), which sits at the top of every scope chain:
Understanding where Scope Chains end is an important part of scoping. All Javascript runtimes must implicitly create a _Global Scope_ object (`window` in the browser, `global` in node), which sits at the top of every scope chain:

```
(global)
Expand All @@ -21,9 +17,7 @@ inner() inner2()
foo()
```

In _Scopes_ we covered how usage of `var` or `let` dictates the scope of the
variable being defined. When assigning a variable without using either of `var`,
`let`, etc, the variable is assumed to exist in an outer scope.
In _Scopes_ we covered how usage of `var` or `let` dictates the scope of the variable being defined. When assigning a variable without using either of `var`, `let`, etc, the variable is assumed to exist in an outer scope.

The javascript runtime follows these steps to assign a variable:

Expand All @@ -49,28 +43,18 @@ function someFunc() {
}
```

Note the lack of `var` or `let`, etc for `foo = 2`. The Javascript runtime will
follow the above algorithm, first checking the scope of `inner()`, then of
`someFunc()`, then finally the Global Scope. Step 5 is then executed, so `foo`
becomes a variable in the Global Scope (`window.foo` / `global.foo`).
Note the lack of `var` or `let`, etc for `foo = 2`. The Javascript runtime will follow the above algorithm, first checking the scope of `inner()`, then of `someFunc()`, then finally the Global Scope. Step 5 is then executed, so `foo` becomes a variable in the Global Scope (`window.foo` / `global.foo`).

Phrased another way: By accidentally forgetting to use `var`, the variable `foo`
which otherwise would have been only within the lexical scope of `inner()` is
now available to be modified by _any_ scope. So, `someFunc()` now has access
where the developer may have meant for it not to.
Phrased another way: By accidentally forgetting to use `var`, the variable `foo` which otherwise would have been only within the lexical scope of `inner()` is
now available to be modified by _any_ scope. So, `someFunc()` now has access where the developer may have meant for it not to.

_Remember: Only inner scopes can access variables of outer scopes. In this case
the `someFunc()` scope is an inner scope of the Global Scope, allowing access of
`foo` to `someFunc()`._
_Remember: Only inner scopes can access variables of outer scopes. In this case the `someFunc()` scope is an inner scope of the Global Scope, allowing access of `foo` to `someFunc()`._

## Shadowing

A variable is created in a 'Step 0)' of the above algorithm: When `var` or `let`
is used. The variable is assigned to the correct scope, then execution moves on,
and any assignments to that variable follow the above algorithm.
A variable is created in a 'Step 0)' of the above algorithm: When `var` or `let` is used. The variable is assigned to the correct scope, then execution moves on, and any assignments to that variable follow the above algorithm.

It is perfectly valid to define two different variables, in different scopes,
with the same name:
It is perfectly valid to define two different variables, in different scopes, with the same name:

```js
function someFunc() {
Expand All @@ -92,24 +76,17 @@ function someFunc() {
}
```

This is called _Shadowing_. The `foo` inside `inner()` is said to _Shadow_ the `foo`
inside `someFunc`.
This is called _Shadowing_. The `foo` inside `inner()` is said to _Shadow_ the `foo` inside `someFunc`.

Shadowing means that the `inner()` scope only has access to its own `foo`. There
is no way for it to access the `foo` defined in `someFunc()`.
Shadowing means that the `inner()` scope only has access to its own `foo`. There is no way for it to access the `foo` defined in `someFunc()`.

This can also be an accidental source of bugs, especially when there is deep
nesting, or long functions.
This can also be an accidental source of bugs, especially when there is deep nesting, or long functions.

----

# Your Mission

Starting with your solution from the previous lesson, assign a value to the global variable
`quux` inside `foo()` (don't use `var` or `let`). Create a shadow variable in of `quux`
inside `zip()`. The value in the global variable `quux` has to be different than the
value of `quux` inside `zip()`.
Starting with your solution from the previous lesson, assign a value to the global variable `quux` inside `foo()` (don't use `var` or `let`). Create a shadow variable in of `quux` inside `zip()`. The value in the global variable `quux` has to be different than the value of `quux` inside `zip()`.

Once complete, execute `$ADVENTURE_COMMAND verify <your-file.js>` to verify your
solution.
Once complete, execute `$ADVENTURE_COMMAND verify <your-file.js>` to verify your solution.

Loading