Skip to content
Merged
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
90 changes: 87 additions & 3 deletions concepts/closures/introduction.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Introduction

**Closures** are a programming pattern in JavaScript that allows variables from an outer [lexical scope][wiki-lexical-scope] to be used inside of a nested block of code. JavaScript supports closures transparently, and they are often used without knowing what they are.
**Closures** are a programming pattern in JavaScript which allows variables from an outer [lexical scope][wiki-lexical-scope] to be used inside of a nested block of code.
JavaScript supports closures transparently, and they are often used without knowing what they are.

```javascript
// Top-level declarations are global-scope
Expand All @@ -12,16 +13,38 @@ const dozen = 12;
const twoDozen = dozen * 2;
}

// Because of the block-scope declaration, twoDozen is not available here.
twoDozen;
// => Uncaught ReferenceError: twoDozen is not defined
```

Except for braces `{}`, functions (and classes) als create new scopes, which can _enclose_ values:

```javascript
const dozen = 12;

// Functions create a new function-scope and block-scope.
// Referencing the outer variable here is a closure.
function nDozen(n) {
return dozen * n;
// This is declared inside the function scope, and uses the top-level scope.
// This works, and encloses the value 12.
const twoDozen = dozen * 2;

// This only uses the locally declared variable and the passed argument to the parameter `n`
return (twoDozen / 2) * n;
}

// Because of the function-scope declaration, twoDozen is not available here.
twoDozen;
// => Uncaught ReferenceError: twoDozen is not defined
```

As the `twoDozen` examples show, values can be enclosed in a _nested_ scope (function, block, etc.), but cannot be pulled out of that context.
In the majority of cases, it is intended in Modern JavaScript that a value does not _leak_ to an outside scope.

## Closures to save state and pass along values

Using a mutable variable declaration (like `let` or `var`) allows for state to be preserved:
Using a mutable variable declaration (like `let` or `var`) allows for some state to be preserved:

```javascript
let counter = 0;
Expand All @@ -32,6 +55,67 @@ export function increment() {
counter += 1;
return counter;
}

increment();
// => 1

counter;
// => 1
```

## Enclosing values without leaking the state

Combining the two ideas: enclosing a value to preserve state, and enclosed values do not leak to the outside, it's possible to create private values.

The most common method is to make a function that returns a function which encloses some state.

```javascript
export function makeCounter() {
let counter = 0;

// This returns a new function that encloses the local variable counter
return function increment() {
counter += 1;
return counter;
};
}

// Counter did not leak
counter;
// => Uncaught ReferenceError: counter is not defined

// This creates a new counter.
// This assigns the increment function to the variable myFirstCounter.
const myFirstCounter = makeCounter();

typeof myFirstCounter;
// => function

myFirstCounter.name;
// => increment

myFirstCounter();
// => 1
myFirstCounter();
// => 2

// This creates new counter (with new, separate local state / enclosed counter variable)
const mySecondCounter = makeCounter();

mySecondCounter();
// => 1

// It is not affect the first counter.

myFirstCounter();
// => 3
```

```exercism/note
Many programmers find closures a hard concept, and returning a function from a function is not common or not even possible in all programming languages.
If you want more reading material, the [guide on MDN on Closures][mdn-closures] is quite comprehensive.

[mdn-closures]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures
```

[wiki-lexical-scope]: https://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scoping
9 changes: 6 additions & 3 deletions exercises/concept/bird-watcher/.docs/instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ To practice, use a `for` loop to solve each of the tasks below.

## 1. Determine the total number of birds that you counted so far

Let us start analyzing the data by getting a high-level view. Find out how many birds you counted in total since you started your logs.
Let us start analyzing the data by getting a high-level view.
Find out how many birds you counted in total since you started your logs.

Implement a function `totalBirdCount` that accepts an array that contains the bird count per day. It should return the total number of birds that you counted.
Implement a function `totalBirdCount` that accepts an array that contains the bird count per day.
It should return the total number of birds that you counted.

```javascript
birdsPerDay = [2, 5, 0, 7, 4, 1, 3, 0, 2, 5, 0, 1, 3, 1];
Expand All @@ -28,7 +30,8 @@ totalBirdCount(birdsPerDay);
Now that you got a general feel for your bird count numbers, you want to make a more fine-grained analysis.

Implement a function `birdsInWeek` that accepts an array of bird counts per day and a week number.
It returns the total number of birds that you counted in that specific week. You can assume weeks are always tracked completely.
It returns the total number of birds that you counted in that specific week.
You can assume weeks are always tracked completely.

```javascript
birdsPerDay = [2, 5, 0, 7, 4, 1, 3, 0, 2, 5, 0, 1, 3, 1];
Expand Down
88 changes: 86 additions & 2 deletions exercises/concept/coordinate-transformation/.docs/introduction.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Introduction

**Closures** are a programming pattern in JavaScript which allows variables from an outer [lexical scope][wiki-lexical-scope] to be used inside of a nested block of code. JavaScript supports closures transparently, and they are often used without knowing what they are.
**Closures** are a programming pattern in JavaScript which allows variables from an outer [lexical scope][wiki-lexical-scope] to be used inside of a nested block of code.
JavaScript supports closures transparently, and they are often used without knowing what they are.

```javascript
// Top-level declarations are global-scope
Expand All @@ -12,13 +13,35 @@ const dozen = 12;
const twoDozen = dozen * 2;
}

// Because of the block-scope declaration, twoDozen is not available here.
twoDozen;
// => Uncaught ReferenceError: twoDozen is not defined
```

Except for braces `{}`, functions (and classes) als create new scopes, which can _enclose_ values:

```javascript
const dozen = 12;

// Functions create a new function-scope and block-scope.
// Referencing the outer variable here is a closure.
function nDozen(n) {
return dozen * n;
// This is declared inside the function scope, and uses the top-level scope.
// This works, and encloses the value 12.
const twoDozen = dozen * 2;

// This only uses the locally declared variable and the passed argument to the parameter `n`
return (twoDozen / 2) * n;
}

// Because of the function-scope declaration, twoDozen is not available here.
twoDozen;
// => Uncaught ReferenceError: twoDozen is not defined
```

As the `twoDozen` examples show, values can be enclosed in a _nested_ scope (function, block, etc.), but cannot be pulled out of that context.
In the majority of cases, it is intended in Modern JavaScript that a value does not _leak_ to an outside scope.

## Closures to save state and pass along values

Using a mutable variable declaration (like `let` or `var`) allows for some state to be preserved:
Expand All @@ -32,6 +55,67 @@ export function increment() {
counter += 1;
return counter;
}

increment();
// => 1

counter;
// => 1
```

## Enclosing values without leaking the state

Combining the two ideas: enclosing a value to preserve state, and enclosed values do not leak to the outside, it's possible to create private values.

The most common method is to make a function that returns a function which encloses some state.

```javascript
export function makeCounter() {
let counter = 0;

// This returns a new function that encloses the local variable counter
return function increment() {
counter += 1;
return counter;
};
}

// Counter did not leak
counter;
// => Uncaught ReferenceError: counter is not defined

// This creates a new counter.
// This assigns the increment function to the variable myFirstCounter.
const myFirstCounter = makeCounter();

typeof myFirstCounter;
// => function

myFirstCounter.name;
// => increment

myFirstCounter();
// => 1
myFirstCounter();
// => 2

// This creates new counter (with new, separate local state / enclosed counter variable)
const mySecondCounter = makeCounter();

mySecondCounter();
// => 1

// It is not affect the first counter.

myFirstCounter();
// => 3
```

```exercism/note
Many programmers find closures a hard concept, and returning a function from a function is not common or not even possible in all programming languages.
If you want more reading material, the [guide on MDN on Closures][mdn-closures] is quite comprehensive.

[mdn-closures]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures
```

[wiki-lexical-scope]: https://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scoping
7 changes: 5 additions & 2 deletions exercises/concept/custom-signs/.docs/instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ In this exercise you'll be writing code to help a sign company create custom mes

## 1. Build an occasion sign

Implement the function `buildSign(occasion, name)` that accepts a string as the `occasion` parameter and a string holding someone's name as the `name` parameter. The two parameters will be embedded into a template string to output the message on the sign.
Implement the function `buildSign(occasion, name)` that accepts a string as the `occasion` parameter and a string holding someone's name as the `name` parameter.
The two parameters will be embedded into a template string to output the message on the sign.

```javascript
buildSign('Birthday', 'Rob');
Expand All @@ -13,7 +14,9 @@ buildSign('Birthday', 'Rob');

## 2. Build a birthday sign

Implement the function `buildBirthdaySign(age)` that accepts an age and based on the age will determine part of the message on the sign. If the age is 50 or older, the sign will refer user as _mature_, else it will refer them as _young_. The exact expected output is shown below:
Implement the function `buildBirthdaySign(age)` that accepts an age and based on the age will determine part of the message on the sign.
If the age is 50 or older, the sign will refer user as _mature_, else it will refer them as _young_.
The exact expected output is shown below:

```javascript
buildBirthdaySign(50);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,13 @@ numbers.indexOf('two');
// => 1
```

Some other helpful built-in methods that are available to analyze an array are shown below. See [MDN][mdn-array-methods] for a full list of array methods.
Some other helpful built-in methods that are available to analyze an array are shown below.
See [MDN][mdn-array-methods] for a full list of array methods.

### `includes`

> The includes() method determines whether an array includes a certain value among its entries, returning true or false as appropriate. [^1]
The `includes(value)` method determines whether an array includes a certain value.
It returns `true` when the value is included, `false` otherwise.

```javascript
const numbers = [1, 'two', 3, 'four'];
Expand All @@ -79,7 +81,10 @@ numbers.includes('one');

### `every`

> The every() method tests whether all elements in the array pass the test implemented by the provided function. It returns a Boolean value. [^2]
The `every(predicate)` method take a function which is _a predicate_.
It tests whether all elements in the array return `true` when passed to the predicate.
In other words: the methods tests that all its elements pass the test passed to the function call.
It returns `true` when every element passes the predicate test, `false` otherwise.

```javascript
const numbers = [1, 3, 5, 7, 9];
Expand All @@ -89,7 +94,7 @@ numbers.every((num) => num % 2 !== 0);

### `some`

> The some() method tests whether at least one element in the array passes the test implemented by the provided function. [^3]
The `some(predicate)` method is the same as the `every` method, but returns `true` if at least one item in the array passes the _predicate_ test.

```javascript
const numbers = [1, 3, 5, 7, 9];
Expand All @@ -99,7 +104,9 @@ numbers.some((num) => num % 2 !== 0);

### `find`

> The find() method returns the value of the first element in the provided array that satisfies the provided testing function. If no values satisfy the testing function, undefined is returned. [^4]
The `find(predicate)` method returns the value of the first element in the array that passes the `predicate` test.
Where `some()` returns `true` when it passes, `find()` returns the actual value in the array.
The method returns `undefined` when none of the elements in the array pass the _predicate_ test.

```javascript
const numbers = [1, 3, 5, 7, 9];
Expand All @@ -109,7 +116,8 @@ numbers.find((num) => num < 5);

### `findIndex`

> The findIndex() method returns the index of the first element in the array that satisfies the provided testing function. Otherwise, it returns -1, indicating that no element passed the test. [^5]
The `findIndex(predicate)` is the same as the `find()` method, but it returns the (first) _index_ of the element that passes the _predicate_ test instead of the `value`.
The method returns `-1` when none of the elements in the array pass the _predicate_ test.

```javascript
const numbers = [1, 3, 5, 7, 9];
Expand All @@ -119,16 +127,6 @@ numbers.findIndex((num) => num > 9);
// => -1
```

[^1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes

[^2]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every

[^3]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some

[^4]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find

[^5]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex

[predicate_in_programming]: https://derk-jan.com/2020/05/predicate/
[mdn-array-methods]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#instance_methods
[arrays-concept]: /tracks/javascript/concepts/arrays
4 changes: 3 additions & 1 deletion exercises/concept/elyses-enchantments/.docs/instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ etc.

<!-- prettier-ignore-start -->
~~~~exercism/note
All functions should update the array of cards and then return the modified array - a common way of working known as the Builder pattern, which allows you to nicely daisy-chain functions together.
All but two functions should update the array of cards and then return the modified array - a common way of working known as the Builder pattern, which allows you to nicely daisy-chain functions together.

The two exceptions are `getItem`, which should return the card at the given position, and `checkSizeOfStack` which should return `true` if the given size matches.
~~~~
<!-- prettier-ignore-end -->

Expand Down
Loading