master e611067ee561 cached
13 files
569.1 KB
179.0k tokens
1 requests
Download .txt
Showing preview only (585K chars total). Download the full file or copy to clipboard to get everything.
Repository: mbeaudru/modern-js-cheatsheet
Branch: master
Commit: e611067ee561
Files: 13
Total size: 569.1 KB

Directory structure:
gitextract__fp8xgmi/

├── LICENSE
├── README.md
├── _config.yml
└── translations/
    ├── de-DE.md
    ├── fa-IR.md
    ├── fr-FR.md
    ├── ja-JP.md
    ├── pl_PL.md
    ├── pt-BR.md
    ├── ru-RU.md
    ├── th-TH.md
    ├── zh-CN.md
    └── zh-TW.md

================================================
FILE CONTENTS
================================================

================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2017 BEAUDRU Manuel

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# Modern JavaScript Cheatsheet

![Modern JavaScript cheatsheet](https://i.imgur.com/aexPxMb.png)
<sub>Image Credits: [Ahmad Awais ⚡️](https://github.com/ahmadawais)</sub>

> If you like this content, you can ping me or follow me on Twitter :+1:

[![Tweet for help](https://img.shields.io/twitter/follow/mbeaudru?label=Tweet%20%40mbeaudru&style=social)](https://twitter.com/mbeaudru/)

## Introduction

### Motivation

This document is a cheatsheet for JavaScript you will frequently encounter in modern projects and most contemporary sample code.

This guide is not intended to teach you JavaScript from the ground up, but to help developers with basic knowledge who may struggle to get familiar with modern codebases (or let's say to learn React for instance) because of the JavaScript concepts used.

Besides, I will sometimes provide personal tips that may be debatable but will take care to mention that it's a personal recommendation when I do so.

> **Note:** Most of the concepts introduced here are coming from a JavaScript language update (ES2015, often called ES6). You can find new features added by this update [here](http://es6-features.org); it's very well done.

### Complementary Resources

When you struggle to understand a notion, I suggest you look for answers on the following resources:

- [MDN (Mozilla Developer Network)](https://developer.mozilla.org/en-US/search?q=)
- [You don't know JS (book)](https://github.com/getify/You-Dont-Know-JS)
- [Eloquent JavaScript (book)](https://eloquentjavascript.net)
- [Douglas Crockford's blog](https://www.crockford.com/javascript/)
- [Wes Bos blog (ES6)](https://wesbos.com/javascript)
- [Javascript Basics for Beginners](https://www.udacity.com/course/javascript-basics--ud804) - a free Udacity course
- [Reddit (JavaScript)](https://www.reddit.com/r/javascript/)
- [Google](https://www.google.com/) to find specific blog and resources
- [StackOverflow](https://stackoverflow.com/questions/tagged/javascript)

## Table of Contents

- [Modern JavaScript cheatsheet](#modern-javascript-cheatsheet)
  * [Introduction](#introduction)
    + [Motivation](#motivation)
    + [Complementary resources](#complementary-resources)
  * [Table of contents](#table-of-contents)
  * [Notions](#notions)
    + [Variable declaration: var, const, let](#variable-declaration-var-const-let)
      - [Short explanation](#short-explanation)
      - [Sample code](#sample-code)
      - [Detailed explanation](#detailed-explanation)
      - [External resource](#external-resource)
    + [Arrow function](#-arrow-function)
      - [Sample code](#sample-code-1)
      - [Detailed explanation](#detailed-explanation-1)
        * [Concision](#concision)
        * [*this* reference](#this-reference)
      - [Useful resources](#useful-resources)
    + [Function default parameter value](#function-default-parameter-value)
      - [External resource](#external-resource-1)
    + [Destructuring objects and arrays](#destructuring-objects-and-arrays)
      - [Explanation with sample code](#explanation-with-sample-code)
      - [Useful resources](#useful-resources-1)
    + [Array methods - map / filter / reduce](#array-methods---map--filter--reduce--find)
      - [Sample code](#sample-code-2)
      - [Explanation](#explanation)
        * [Array.prototype.map()](#arrayprototypemap)
        * [Array.prototype.filter()](#arrayprototypefilter)
        * [Array.prototype.reduce()](#arrayprototypereduce)
        * [Array.prototype.find()](#arrayprototypefind)
      - [External Resource](#external-resource-2)
    + [Spread operator "..."](#spread-operator-)
      - [Sample code](#sample-code-3)
      - [Explanation](#explanation-1)
        * [In iterables (like arrays)](#in-iterables-like-arrays)
        * [Function rest parameter](#function-rest-parameter)
        * [Object properties spreading](#object-properties-spreading)
      - [External resources](#external-resources)
    + [Object property shorthand](#object-property-shorthand)
      - [Explanation](#explanation-2)
      - [External resources](#external-resources-1)
    + [Promises](#promises)
      - [Sample code](#sample-code-4)
      - [Explanation](#explanation-3)
        * [Create the promise](#create-the-promise)
        * [Promise handlers usage](#promise-handlers-usage)
      - [External Resources](#external-resources-2)
    + [Template literals](#template-literals)
      - [Sample code](#sample-code-5)
      - [External resources](#external-resources-3)
    + [Tagged Template Literals](#tagged-template-literals)
      - [External resources](#external-resources-4)
    + [Imports / Exports](#imports--exports)
      - [Explanation with sample code](#explanation-with-sample-code-1)
        * [Named exports](#named-exports)
        * [Default import / export](#default-import--export)
      - [External resources](#external-resources-5)
    + [JavaScript *this*](#-javascript-this)
      - [External resources](#external-resources-6)
    + [Class](#class)
      - [Samples](#samples)
      - [External resources](#external-resources-7)
    + [Extends and super keywords](#extends-and-super-keywords)
      - [Sample Code](#sample-code-6)
      - [External Resources](#external-resources-8)
    + [Async Await](#async-await)
      - [Sample code](#sample-code-7)
      - [Explanation with sample code](#explanation-with-sample-code-2)
      - [Error handling](#error-handling)
      - [External resources](#external-resources-9)
    + [Truthy / Falsy](#truthy--falsy)
      - [External resources](#external-resources-10)
    + [Anamorphisms / Catamporphisms](#anamorphisms-and-catamorphisms)
      - [Anamorphisms](#anamorphisms)
      - [Catamorphisms](#catamorphisms)
      - [External resources](#external-resources-11)
    + [Generators](#generators)
      - [External resources](#external-resources-12)
    + [Static Methods](#static-methods)
      - [Short Explanation](#short-explanation-1)
      - [Sample Code](#sample-code-8)
      - [Detailed Explanation](#detailed-explanation-2)
        * [Calling other static methods from a static method](#calling-other-static-methods-from-a-static-method)
        * [Calling static methods from non-static methods](#calling-static-methods-from-non-static-methods)
      - [External resources](#external-resources-13)
  * [Glossary](#glossary)
    + [Scope](#-scope)
    + [Variable mutation](#-variable-mutation)

## Notions

### Variable declaration: var, const, let

In JavaScript, there are three keywords available to declare a variable, and each has its differences. Those are ```var```, ```let``` and ```const```.

#### Short explanation

Variables declared with ```const``` keyword can't be reassigned, while ```let``` and ```var``` can.

I recommend always declaring your variables with ```const``` by default, but with ```let``` if it is a variable that you need to *mutate* or reassign later.

<table>
  <tr>
    <th></th>
    <th>Scope</th>
    <th>Reassignable</th>
    <th>Mutable</th>
   <th><a href="#tdz_sample">Temporal Dead Zone</a></th>
  </tr>
  <tr>
    <th>const</th>
    <td>Block</td>
    <td>No</td>
    <td><a href="#const_mutable_sample">Yes</a></td>
    <td>Yes</td>
  </tr>
  <tr>
    <th>let</th>
    <td>Block</td>
    <td>Yes</td>
    <td>Yes</td>
    <td>Yes</td>
  </tr>
   <tr>
    <th>var</th>
    <td>Function</td>
    <td>Yes</td>
    <td>Yes</td>
    <td>No</td>
  </tr>
</table>

#### Sample code

```javascript
const person = "Nick";
person = "John" // Will raise an error, person can't be reassigned
```

```javascript
let person = "Nick";
person = "John";
console.log(person) // "John", reassignment is allowed with let
```

#### Detailed explanation

The [*scope*](#scope_def) of a variable roughly means "where is this variable available in the code".

##### var

```var``` declared variables are *function scoped*, meaning that when a variable is created in a function, everything in that function can access that variable. Besides, a *function scoped* variable created in a function can't be accessed outside this function.

I recommend you to picture it as if an *X scoped* variable meant that this variable was a property of X.

```javascript
function myFunction() {
  var myVar = "Nick";
  console.log(myVar); // "Nick" - myVar is accessible inside the function
}
console.log(myVar); // Throws a ReferenceError, myVar is not accessible outside the function.
```

Still focusing on the variable scope, here is a more subtle example:

```javascript
function myFunction() {
  var myVar = "Nick";
  if (true) {
    var myVar = "John";
    console.log(myVar); // "John"
    // actually, myVar being function scoped, we just erased the previous myVar value "Nick" for "John"
  }
  console.log(myVar); // "John" - see how the instructions in the if block affected this value
}
console.log(myVar); // Throws a ReferenceError, myVar is not accessible outside the function.
```

Besides, *var* declared variables are moved to the top of the scope at execution. This is what we call [var hoisting](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var#var_hoisting).

This portion of code:

```js
console.log(myVar) // undefined -- no error raised
var myVar = 2;
```

is understood at execution like:

```js
var myVar;
console.log(myVar) // undefined -- no error raised
myVar = 2;
```

##### let

```var``` and ```let ``` are about the same, but ```let``` declared variables

- are *block scoped*
- are **not** accessible before they are assigned
- can't be re-declared in the same scope

Let's see the impact of block-scoping taking our previous example:

```javascript
function myFunction() {
  let myVar = "Nick";
  if (true) {
    let myVar = "John";
    console.log(myVar); // "John"
    // actually, myVar being block scoped, we just created a new variable myVar.
    // this variable is not accessible outside this block and totally independent
    // from the first myVar created !
  }
  console.log(myVar); // "Nick", see how the instructions in the if block DID NOT affect this value
}
console.log(myVar); // Throws a ReferenceError, myVar is not accessible outside the function.
```

<a name="tdz_sample"></a> Now, what it means for *let* (and *const*) variables for not being accessible before being assigned:

```js
console.log(myVar) // raises a ReferenceError !
let myVar = 2;
```

By contrast with *var* variables, if you try to read or write on a *let* or *const* variable before they are assigned an error will be raised. This phenomenon is often called [*Temporal dead zone*](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#Temporal_Dead_Zone_and_errors_with_let) or *TDZ*.

> **Note:** Technically, *let* and *const* variables declarations are being hoisted too, but not their assignation. Since they're made so that they can't be used before assignation, it intuitively feels like there is no hoisting, but there is. Find out more on this [very detailed explanation here](http://jsrocks.org/2015/01/temporal-dead-zone-tdz-demystified) if you want to know more.

In addition, you can't re-declare a *let* variable:

```js
let myVar = 2;
let myVar = 3; // Raises a SyntaxError
```

##### const

```const``` declared variables behave like *let* variables, but also they can't be reassigned.

To sum it up, *const* variables:

- are *block scoped*
- are not accessible before being assigned
- can't be re-declared in the same scope
- can't be reassigned

```js
const myVar = "Nick";
myVar = "John" // raises an error, reassignment is not allowed
```

```js
const myVar = "Nick";
const myVar = "John" // raises an error, re-declaration is not allowed
```

<a name="const_mutable_sample"></a> But there is a subtlety : ```const``` variables are not [**immutable**](#mutation_def) ! Concretely, it means that *object* and *array* ```const``` declared variables **can** be mutated.

For objects:
```js
const person = {
  name: 'Nick'
};
person.name = 'John' // this will work ! person variable is not completely reassigned, but mutated
console.log(person.name) // "John"
person = "Sandra" // raises an error, because reassignment is not allowed with const declared variables
```

For arrays:
```js
const person = [];
person.push('John'); // this will work ! person variable is not completely reassigned, but mutated
console.log(person[0]) // "John"
person = ["Nick"] // raises an error, because reassignment is not allowed with const declared variables
```

#### External resource

- [How let and const are scoped in JavaScript - WesBos](http://wesbos.com/javascript-scoping/)
- [Temporal Dead Zone (TDZ) Demystified](http://jsrocks.org/2015/01/temporal-dead-zone-tdz-demystified)

### <a name="arrow_func_concept"></a> Arrow function

The ES6 JavaScript update has introduced *arrow functions*, which is another way to declare and use functions. Here are the benefits they bring:

- More concise
- *this* is picked up from surroundings
- implicit return

#### Sample code

- Concision and implicit return

```js
function double(x) { return x * 2; } // Traditional way
console.log(double(2)) // 4
```

```js
const double = x => x * 2; // Same function written as an arrow function with implicit return
console.log(double(2)) // 4
```

- *this* reference

In an arrow function, *this* is equal to the *this* value of the enclosing execution context. Basically, with arrow functions, you don't have to do the "that = this" trick before calling a function inside a function anymore.

```js
function myFunc() {
  this.myVar = 0;
  setTimeout(() => {
    this.myVar++;
    console.log(this.myVar) // 1
  }, 0);
}
```

#### Detailed explanation

##### Concision

Arrow functions are more concise than traditional functions in many ways. Let's review all the possible cases:

- Implicit VS Explicit return

An **explicit return** is a function where the *return* keyword is used in its body.

```js
  function double(x) {
    return x * 2; // this function explicitly returns x * 2, *return* keyword is used
  }
```

In the traditional way of writing functions, the return was always explicit. But with arrow functions, you can do *implicit return* which means that you don't need to use the keyword *return* to return a value.

```js
  const double = (x) => {
    return x * 2; // Explicit return here
  }
```

Since this function only returns something (no instructions before the *return* keyword) we can do an implicit return.

```js
  const double = (x) => x * 2; // Correct, returns x*2
```

To do so, we only need to **remove the brackets** and the **return** keyword. That's why it's called an *implicit* return, the *return* keyword is not there, but this function will indeed return ```x * 2```.

> **Note:** If your function does not return a value (with *side effects*), it doesn't do an explicit nor an implicit return.

Besides, if you want to implicitly return an *object* you **must have parentheses around it** since it will conflict with the block braces:

```js
const getPerson = () => ({ name: "Nick", age: 24 })
console.log(getPerson()) // { name: "Nick", age: 24 } -- object implicitly returned by arrow function
```

- Only one argument

If your function only takes one parameter, you can omit the parentheses around it. If we take back the above *double* code:

```js
  const double = (x) => x * 2; // this arrow function only takes one parameter
```

Parentheses around the parameter can be avoided:

```js
  const double = x => x * 2; // this arrow function only takes one parameter
```

- No arguments

When there is no argument provided to an arrow function, you need to provide parentheses, or it won't be valid syntax.

```js
  () => { // parentheses are provided, everything is fine
    const x = 2;
    return x;
  }
```

```js
  => { // No parentheses, this won't work!
    const x = 2;
    return x;
  }
```

##### *this* reference

To understand this subtlety introduced with arrow functions, you must know how [this](#this_def) behaves in JavaScript.

In an arrow function, *this* is equal to the *this* value of the enclosing execution context. What it means is that an arrow function doesn't create a new *this*, it grabs it from its surrounding instead.

Without arrow function, if you wanted to access a variable from *this* in a function inside a function, you had to use the *that = this* or *self = this* trick.

For instance, using setTimeout function inside myFunc:

```js
function myFunc() {
  this.myVar = 0;
  var that = this; // that = this trick
  setTimeout(
    function() { // A new *this* is created in this function scope
      that.myVar++;
      console.log(that.myVar) // 1

      console.log(this.myVar) // undefined -- see function declaration above
    },
    0
  );
}
```

But with arrow function, *this* is taken from its surrounding:

```js
function myFunc() {
  this.myVar = 0;
  setTimeout(
    () => { // this taken from surrounding, meaning myFunc here
      this.myVar++;
      console.log(this.myVar) // 1
    },
    0
  );
}
```

#### Useful resources

- [Arrow functions introduction - WesBos](http://wesbos.com/arrow-functions/)
- [JavaScript arrow function - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)
- [Arrow function and lexical *this*](https://hackernoon.com/javascript-es6-arrow-functions-and-lexical-this-f2a3e2a5e8c4)

### Function default parameter value

Starting from ES2015 JavaScript update, you can set default value to your function parameters using the following syntax:

```js
function myFunc(x = 10) {
  return x;
}
console.log(myFunc()) // 10 -- no value is provided so x default value 10 is assigned to x in myFunc
console.log(myFunc(5)) // 5 -- a value is provided so x is equal to 5 in myFunc

console.log(myFunc(undefined)) // 10 -- undefined value is provided so default value is assigned to x
console.log(myFunc(null)) // null -- a value (null) is provided, see below for more details
```

The default parameter is applied in two and only two situations:

- No parameter provided
- *undefined* parameter provided

In other words, if you pass in *null* the default parameter **won't be applied**.

> **Note:** Default value assignment can be used with destructured parameters as well (see next notion to see an example)

#### External resource

- [Default parameter value - ES6 Features](http://es6-features.org/#DefaultParameterValues)
- [Default parameters - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters)

### Destructuring objects and arrays

*Destructuring* is a convenient way of creating new variables by extracting some values from data stored in objects or arrays.

To name a few use cases, *destructuring* can be used to destructure function parameters or *this.props* in React projects for instance.

#### Explanation with sample code

- Object

Let's consider the following object for all the samples:

```js
const person = {
  firstName: "Nick",
  lastName: "Anderson",
  age: 35,
  sex: "M"
}
```

Without destructuring

```js
const first = person.firstName;
const age = person.age;
const city = person.city || "Paris";
```

With destructuring, all in one line:

```js
const { firstName: first, age, city = "Paris" } = person; // That's it !

console.log(age) // 35 -- A new variable age is created and is equal to person.age
console.log(first) // "Nick" -- A new variable first is created and is equal to person.firstName
console.log(firstName) // ReferenceError -- person.firstName exists BUT the new variable created is named first
console.log(city) // "Paris" -- A new variable city is created and since person.city is undefined, city is equal to the default value provided "Paris".
```

**Note :** In ```const { age } = person;```, the brackets after *const* keyword are not used to declare an object nor a block but is the *destructuring* syntax.

- Function parameters

*Destructuring* is often used to destructure objects parameters in functions.

Without destructuring

```js
function joinFirstLastName(person) {
  const firstName = person.firstName;
  const lastName = person.lastName;
  return firstName + '-' + lastName;
}

joinFirstLastName(person); // "Nick-Anderson"
```

In destructuring the object parameter *person*, we get a more concise function:

```js
function joinFirstLastName({ firstName, lastName }) { // we create firstName and lastName variables by destructuring person parameter
  return firstName + '-' + lastName;
}

joinFirstLastName(person); // "Nick-Anderson"
```

Destructuring is even more pleasant to use with [arrow functions](#arrow_func_concept):

```js
const joinFirstLastName = ({ firstName, lastName }) => firstName + '-' + lastName;

joinFirstLastName(person); // "Nick-Anderson"
```

- Array

Let's consider the following array:

```js
const myArray = ["a", "b", "c"];
```

Without destructuring

```js
const x = myArray[0];
const y = myArray[1];
```

With destructuring

```js
const [x, y] = myArray; // That's it !

console.log(x) // "a"
console.log(y) // "b"
```

#### Useful resources

- [ES6 Features - Destructuring Assignment](http://es6-features.org/#ArrayMatching)
- [Destructuring Objects - WesBos](http://wesbos.com/destructuring-objects/)
- [ExploringJS - Destructuring](http://exploringjs.com/es6/ch_destructuring.html)

### Array methods - map / filter / reduce / find

*Map*, *filter*, *reduce* and *find* are array methods that are coming from a programming paradigm named [*functional programming*](https://medium.com/javascript-scene/master-the-javascript-interview-what-is-functional-programming-7f218c68b3a0).

To sum it up:

- **Array.prototype.map()** takes an array, does something on its elements and returns an array with the transformed elements.
- **Array.prototype.filter()** takes an array, decides element by element if it should keep it or not and returns an array with the kept elements only
- **Array.prototype.reduce()** takes an array and aggregates the elements into a single value (which is returned)
- **Array.prototype.find()** takes an array, and returns the first element that satisfies the provided condition.

I recommend to use them as much as possible in following the principles of functional programming because they are composable, concise and elegant.

With those four methods, you can avoid the use of *for* and *forEach* loops in most situations. When you are tempted to do a *for* loop, try to do it with *map*, *filter*, *reduce* and *find* composed. You might struggle to do it at first because it requires you to learn a new way of thinking, but once you've got it things get easier.

#### Sample code

```js
const numbers = [0, 1, 2, 3, 4, 5, 6];
const doubledNumbers = numbers.map(n => n * 2); // [0, 2, 4, 6, 8, 10, 12]
const evenNumbers = numbers.filter(n => n % 2 === 0); // [0, 2, 4, 6]
const sum = numbers.reduce((prev, next) => prev + next, 0); // 21
const greaterThanFour = numbers.find((n) => n>4); // 5
```

Compute total grade sum for students with grades 10 or above by composing map, filter and reduce:

```js
const students = [
  { name: "Nick", grade: 10 },
  { name: "John", grade: 15 },
  { name: "Julia", grade: 19 },
  { name: "Nathalie", grade: 9 },
];

const aboveTenSum = students
  .map(student => student.grade) // we map the students array to an array of their grades
  .filter(grade => grade >= 10) // we filter the grades array to keep those 10 or above
  .reduce((prev, next) => prev + next, 0); // we sum all the grades 10 or above one by one

console.log(aboveTenSum) // 44 -- 10 (Nick) + 15 (John) + 19 (Julia), Nathalie below 10 is ignored
```

#### Explanation

Let's consider the following array of numbers for our examples:

```js
const numbers = [0, 1, 2, 3, 4, 5, 6];
```

##### Array.prototype.map()

```js
const doubledNumbers = numbers.map(function(n) {
  return n * 2;
});
console.log(doubledNumbers); // [0, 2, 4, 6, 8, 10, 12]
```

What's happening here? We are using .map on the *numbers* array, the map is iterating on each element of the array and passes it to our function. The goal of the function is to produce and return a new value from the one passed so that map can replace it.

Let's extract this function to make it more clear, just for this once:

```js
const doubleN = function(n) { return n * 2; };
const doubledNumbers = numbers.map(doubleN);
console.log(doubledNumbers); // [0, 2, 4, 6, 8, 10, 12]
```

**Note** : You will frequently encounter this method used in combination with [arrow functions](#-arrow-function)

```js
const doubledNumbers = numbers.map(n => n * 2);
console.log(doubledNumbers); // [0, 2, 4, 6, 8, 10, 12]
```

```numbers.map(doubleN)``` produces ```[doubleN(0), doubleN(1), doubleN(2), doubleN(3), doubleN(4), doubleN(5), doubleN(6)]``` which is equal to ```[0, 2, 4, 6, 8, 10, 12]```.

> **Note:** If you do not need to return a new array and just want to do a loop that has side effects, you might just want to use a for / forEach loop instead of a map.

##### Array.prototype.filter()

```js
const evenNumbers = numbers.filter(function(n) {
  return n % 2 === 0; // true if "n" is par, false if "n" isn't
});
console.log(evenNumbers); // [0, 2, 4, 6]
```

**Note** : You will frequently encounter this method used in combination with [arrow functions](#-arrow-function)

```js
const evenNumbers = numbers.filter(n => n % 2 === 0);
console.log(evenNumbers); // [0, 2, 4, 6]
```

We are using .filter on the *numbers* array, filter is iterating on each element of the array and passes it to our function. The goal of the function is to return a boolean that will determine whether the current value will be kept or not. Filter then returns the array with only the kept values.

##### Array.prototype.reduce()

The reduce method goal is to *reduce* all elements of the array it iterates on into a single value. How it aggregates those elements is up to you.

```js
const sum = numbers.reduce(
  function(acc, n) {
    return acc + n;
  },
  0 // accumulator variable value at first iteration step
);

console.log(sum) // 21
```

**Note** : You will frequently encounter this method used in combination with [arrow functions](#-arrow-function)

```js
const sum = numbers.reduce((acc, n) => acc + n, 0);
console.log(sum) // 21
```

Just like for .map and .filter methods, .reduce is applied on an array and takes a function as the first parameter.

This time though, there are changes:

- .reduce takes two parameters

The first parameter is a function that will be called at each iteration step.

The second parameter is the value of the accumulator variable (*acc* here) at the first iteration step (read next point to understand).

- Function parameters

The function you pass as the first parameter of .reduce takes two parameters. The first one (*acc* here) is the accumulator variable, whereas the second parameter (*n*) is the current element.

The accumulator variable is equal to the return value of your function at the **previous** iteration step. At the first step of the iteration, *acc* is equal to the value you passed as .reduce second parameter.

###### At first iteration step

```acc = 0``` because we passed in 0 as the second parameter for reduce

```n = 0``` first element of the *number* array

Function returns *acc* + *n* --> 0 + 0 --> 0

###### At second iteration step

```acc = 0``` because it's the value the function returned at the previous iteration step

```n = 1``` second element of the *number* array

Function returns *acc* + *n* --> 0 + 1 --> 1

###### At third iteration step

```acc = 1``` because it's the value the function returned at the previous iteration step

```n = 2``` third element of the *number* array

Function returns *acc* + *n* --> 1 + 2 --> 3

###### At fourth iteration step

```acc = 3``` because it's the value the function returned at the previous iteration step

```n = 3``` fourth element of the *number* array

Function returns *acc* + *n* --> 3 + 3 --> 6

###### [...] At last iteration step

```acc = 15``` because it's the value the function returned at the previous iteration step

```n = 6``` last element of the *number* array

Function returns *acc* + *n* --> 15 + 6 --> 21

As it is the last iteration step, **.reduce** returns 21.

##### Array.prototype.find()

```js
const greaterThanZero = numbers.find(function(n) {
  return n > 0; // return number just greater than 0 is present
});
console.log(greaterThanZero); // 1
```

**Note** : You will frequently encounter this method used in combination with [arrow functions](#-arrow-function)

We are using .find on the *numbers* array, .find is iterating on each element of the array and passes it to our function, until the condition is met. The goal of the function is to return the element that satisfies the current testing function. The .find method executes the callback function once for each index of the array until the callback returns a truthy value.

**Note** : It immediately returns the value of that element (that satisfies the condition) if found. Otherwise, returns undefined.

#### External Resource

- [Understanding map / filter / reduce in JS](https://hackernoon.com/understanding-map-filter-and-reduce-in-javascript-5df1c7eee464)

### Spread operator "..."

The spread operator ```...``` has been introduced with ES2015 and is used to expand elements of an iterable (like an array) into places where multiple elements can fit.

#### Sample code

```js
const arr1 = ["a", "b", "c"];
const arr2 = [...arr1, "d", "e", "f"]; // ["a", "b", "c", "d", "e", "f"]
```

```js
function myFunc(x, y, ...params) {
  console.log(x);
  console.log(y);
  console.log(params)
}

myFunc("a", "b", "c", "d", "e", "f")
// "a"
// "b"
// ["c", "d", "e", "f"]
```

```js
const { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
console.log(x); // 1
console.log(y); // 2
console.log(z); // { a: 3, b: 4 }

const n = { x, y, ...z };
console.log(n); // { x: 1, y: 2, a: 3, b: 4 }
```

#### Explanation

##### In iterables (like arrays)

If we have the two following arrays:

```js
const arr1 = ["a", "b", "c"];
const arr2 = [arr1, "d", "e", "f"]; // [["a", "b", "c"], "d", "e", "f"]
```

*arr2* the first element is an array because *arr1* is injected as is into *arr2*. But what we want is *arr2* to be an array of letters. To do so, we can *spread* the elements of *arr1* into *arr2*.

With spread operator

```js
const arr1 = ["a", "b", "c"];
const arr2 = [...arr1, "d", "e", "f"]; // ["a", "b", "c", "d", "e", "f"]
```

##### Function rest parameter

In function parameters, we can use the rest operator to inject parameters into an array we can loop in. There is already an **arguments** object bound to every function that is equal to an array of all the parameters passed into the function.

```js
function myFunc() {
  for (var i = 0; i < arguments.length; i++) {
    console.log(arguments[i]);
  }
}

myFunc("Nick", "Anderson", 10, 12, 6);
// "Nick"
// "Anderson"
// 10
// 12
// 6
```

But let's say that we want this function to create a new student with its grades and with its average grade. Wouldn't it be more convenient to extract the first two parameters into two separate variables, and then have all the grades in an array we can iterate over?

That's exactly what the rest operator allows us to do!

```js
function createStudent(firstName, lastName, ...grades) {
  // firstName = "Nick"
  // lastName = "Anderson"
  // [10, 12, 6] -- "..." takes all other parameters passed and creates a "grades" array variable that contains them

  const avgGrade = grades.reduce((acc, curr) => acc + curr, 0) / grades.length; // computes average grade from grades

  return {
    firstName: firstName,
    lastName: lastName,
    grades: grades,
    avgGrade: avgGrade
  }
}

const student = createStudent("Nick", "Anderson", 10, 12, 6);
console.log(student);
// {
//   firstName: "Nick",
//   lastName: "Anderson",
//   grades: [10, 12, 6],
//   avgGrade: 9,33
// }
```

> **Note:** createStudent function is bad because we don't check if grades.length exists or is different from 0. But it's easier to read this way, so I didn't handle this case.

##### Object properties spreading

For this one, I recommend you read previous explanations about the rest operator on iterables and function parameters.

```js
const myObj = { x: 1, y: 2, a: 3, b: 4 };
const { x, y, ...z } = myObj; // object destructuring here
console.log(x); // 1
console.log(y); // 2
console.log(z); // { a: 3, b: 4 }

// z is the rest of the object destructured: myObj object minus x and y properties destructured

const n = { x, y, ...z };
console.log(n); // { x: 1, y: 2, a: 3, b: 4 }

// Here z object properties are spread into n
```

#### External resources

- [TC39 - Object rest/spread](https://github.com/tc39/proposal-object-rest-spread)
- [Spread operator introduction - WesBos](https://github.com/wesbos/es6-articles/blob/master/28%20-%20Spread%20Operator%20Introduction.md)
- [JavaScript & the spread operator](https://codeburst.io/javascript-the-spread-operator-a867a71668ca)
- [6 Great uses of the spread operator](https://davidwalsh.name/spread-operator)

### Object property shorthand

When assigning a variable to an object property, if the variable name is equal to the property name, you can do the following:

```js
const x = 10;
const myObj = { x };
console.log(myObj.x) // 10
```

#### Explanation

Usually (pre-ES2015) when you declare a new *object literal* and want to use variables as object properties values, you would write this kind of code:

```js
const x = 10;
const y = 20;

const myObj = {
  x: x, // assigning x variable value to myObj.x
  y: y // assigning y variable value to myObj.y
};

console.log(myObj.x) // 10
console.log(myObj.y) // 20
```

As you can see, this is quite repetitive because the properties name of myObj are the same as the variable names you want to assign to those properties.

With ES2015, when the variable name is the same as the property name, you can do this shorthand:

```js
const x = 10;
const y = 20;

const myObj = {
  x,
  y
};

console.log(myObj.x) // 10
console.log(myObj.y) // 20
```

#### External resources

- [Property shorthand - ES6 Features](http://es6-features.org/#PropertyShorthand)

### Promises

A promise is an object which can be returned synchronously from an asynchronous function ([ref](https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-promise-27fc71e77261#3cd0)).

Promises can be used to avoid [callback hell](http://callbackhell.com/), and they are more and more frequently encountered in modern JavaScript projects.

#### Sample code

```js
const fetchingPosts = new Promise((res, rej) => {
  $.get("/posts")
    .done(posts => res(posts))
    .fail(err => rej(err));
});

fetchingPosts
  .then(posts => console.log(posts))
  .catch(err => console.log(err));
```

#### Explanation

When you do an *Ajax request* the response is not synchronous because you want a resource that takes some time to come. It even may never come if the resource you have requested is unavailable for some reason (404).

To handle that kind of situation, ES2015 has given us *promises*. Promises can have three different states:

- Pending
- Fulfilled
- Rejected

Let's say we want to use promises to handle an Ajax request to fetch the resource X.

##### Create the promise

We firstly are going to create a promise. We will use the jQuery get method to do our Ajax request to X.

```js
const xFetcherPromise = new Promise( // Create promise using "new" keyword and store it into a variable
  function(resolve, reject) { // Promise constructor takes a function parameter which has resolve and reject parameters itself
    $.get("X") // Launch the Ajax request
      .done(function(X) { // Once the request is done...
        resolve(X); // ... resolve the promise with the X value as parameter
      })
      .fail(function(error) { // If the request has failed...
        reject(error); // ... reject the promise with the error as parameter
      });
  }
)
```

As seen in the above sample, the Promise object takes an *executor* function which takes two parameters **resolve** and **reject**. Those parameters are functions which when called are going to move the promise *pending* state to respectively a *fulfilled* and *rejected* state.

The promise is in pending state after instance creation and its *executor* function is executed immediately. Once one of the function *resolve* or *reject* is called in the *executor* function, the promise will call its associated handlers.

##### Promise handlers usage

To get the promise result (or error), we must attach to it handlers by doing the following:

```js
xFetcherPromise
  .then(function(X) {
    console.log(X);
  })
  .catch(function(err) {
    console.log(err)
  })
```

If the promise succeeds, *resolve* is executed and the function passed as ```.then``` parameter is executed.

If it fails, *reject* is executed and the function passed as ```.catch``` parameter is executed.

> **Note :** If the promise has already been fulfilled or rejected when a corresponding handler is attached, the handler will be called, so there is no race condition between an asynchronous operation completing and its handlers being attached. [(Ref: MDN)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise#Description)

#### External Resources

- [JavaScript Promises for dummies - Jecelyn Yeen](https://scotch.io/tutorials/javascript-promises-for-dummies)
- [JavaScript Promise API - David Walsh](https://davidwalsh.name/promises)
- [Using promises - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises)
- [What is a promise - Eric Elliott](https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-promise-27fc71e77261)
- [JavaScript Promises: an Introduction - Jake Archibald](https://developers.google.com/web/fundamentals/getting-started/primers/promises)
- [Promise documentation - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)

### Template literals

Template literals is an [*expression interpolation*](https://en.wikipedia.org/wiki/String_interpolation) for single and multiple-line strings.

In other words, it is a new string syntax in which you can conveniently use any JavaScript expressions (variables for instance).

#### Sample code

```js
const name = "Nick";
`Hello ${name}, the following expression is equal to four : ${2+2}`;

// Hello Nick, the following expression is equal to four: 4
```

#### External resources

- [String interpolation - ES6 Features](http://es6-features.org/#StringInterpolation)
- [ES6 Template Strings - Addy Osmani](https://developers.google.com/web/updates/2015/01/ES6-Template-Strings)

### Tagged template literals

Template tags are *functions that can be prefixed to a [template literal](#template-literals)*. When a function is called this way, the first parameter is an array of the *strings* that appear between the template's interpolated variables, and the subsequent parameters are the interpolated values. Use a spread operator `...` to capture all of them. [(Ref: MDN)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_template_literals).

> **Note :** A famous library named [styled-components](https://www.styled-components.com/) heavily relies on this feature.

Below is a toy example on how they work.
```js
function highlight(strings, ...values) {
  const interpolation = strings.reduce((prev, current) => {
    return prev + current + (values.length ? "<mark>" + values.shift() + "</mark>" : "");
  }, "");

  return interpolation;
}

const condiment = "jam";
const meal = "toast";

highlight`I like ${condiment} on ${meal}.`;
// "I like <mark>jam</mark> on <mark>toast</mark>."
```

A more interesting example:
```js
function comma(strings, ...values) {
  return strings.reduce((prev, next) => {
    let value = values.shift() || [];
    value = value.join(", ");
    return prev + next + value;
  }, "");
}

const snacks = ['apples', 'bananas', 'cherries'];
comma`I like ${snacks} to snack on.`;
// "I like apples, bananas, cherries to snack on."
```

#### External resources
- [Wes Bos on Tagged Template Literals](http://wesbos.com/tagged-template-literals/)
- [Library of common template tags](https://github.com/declandewet/common-tags)

### Imports / Exports

ES6 modules are used to access variables or functions in a module explicitly exported by the modules it imports.

I highly recommend to take a look at MDN resources on import/export (see external resources below), it is both straightforward and complete.

#### Explanation with sample code

##### Named exports

Named exports are used to export several values from a module.

> **Note :** You can only name-export [first-class citizens](https://en.wikipedia.org/wiki/First-class_citizen) that have a name.

```js
// mathConstants.js
export const pi = 3.14;
export const exp = 2.7;
export const alpha = 0.35;

// -------------

// myFile.js
import { pi, exp } from './mathConstants.js'; // Named import -- destructuring-like syntax
console.log(pi) // 3.14
console.log(exp) // 2.7

// -------------

// mySecondFile.js
import * as constants from './mathConstants.js'; // Inject all exported values into constants variable
console.log(constants.pi) // 3.14
console.log(constants.exp) // 2.7
```

While named imports looks like *destructuring*, they have a different syntax and are not the same. They don't support default values nor *deep* destructuring.

Besides, you can do aliases but the syntax is different from the one used in destructuring:

```js
import { foo as bar } from 'myFile.js'; // foo is imported and injected into a new bar variable
```

##### Default import / export

Concerning the default export, there is only a single default export per module. A default export can be a function, a class, an object or anything else. This value is considered the "main" exported value since it will be the simplest to import. [Ref: MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export#Description)

```js
// coolNumber.js
const ultimateNumber = 42;
export default ultimateNumber;

// ------------

// myFile.js
import number from './coolNumber.js';
// Default export, independently from its name, is automatically injected into number variable;
console.log(number) // 42
```

Function exporting:

```js
// sum.js
export default function sum(x, y) {
  return x + y;
}
// -------------

// myFile.js
import sum from './sum.js';
const result = sum(1, 2);
console.log(result) // 3
```

#### External resources

- [ES6 Modules in bulletpoints](https://ponyfoo.com/articles/es6#modules)
- [Export - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export)
- [Import - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import)
- [Understanding ES6 Modules](https://www.sitepoint.com/understanding-es6-modules/)
- [Destructuring special case - import statements](https://ponyfoo.com/articles/es6-destructuring-in-depth#special-case-import-statements)
- [Misunderstanding ES6 Modules - Kent C. Dodds](https://medium.com/@kentcdodds/misunderstanding-es6-modules-upgrading-babel-tears-and-a-solution-ad2d5ab93ce0)
- [Modules in JavaScript](http://exploringjs.com/es6/ch_modules.html#sec_modules-in-javascript)

### <a name="this_def"></a> JavaScript *this*

*this* operator behaves differently than in other languages and is in most cases determined by how a function is called. ([Ref: MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this)).

This notion is having many subtleties and being quite hard, I highly suggest you to deep dive in the external resources below. Thus, I will provide what I personally have in mind to determine what *this* is equal to. I have learned this tip from [this article written by Yehuda Katz](http://yehudakatz.com/2011/08/11/understanding-javascript-function-invocation-and-this/).

```js
function myFunc() {
  ...
}

// After each statement, you find the value of *this* in myFunc

myFunc.call("myString", "hello") // "myString" -- first .call parameter value is injected into *this*

// In non-strict-mode
myFunc("hello") // window -- myFunc() is syntax sugar for myFunc.call(window, "hello")

// In strict-mode
myFunc("hello") // undefined -- myFunc() is syntax sugar for myFunc.call(undefined, "hello")
```

```js
var person = {
  myFunc: function() { ... }
}

person.myFunc.call(person, "test") // person Object -- first call parameter is injected into *this*
person.myFunc("test") // person Object -- person.myFunc() is syntax sugar for person.myFunc.call(person, "test")

var myBoundFunc = person.myFunc.bind("hello") // Creates a new function in which we inject "hello" in *this* value
person.myFunc("test") // person Object -- The bind method has no effect on the original method
myBoundFunc("test") // "hello" -- myBoundFunc is person.myFunc with "hello" bound to *this*
```

#### External resources

- [Understanding JavaScript Function Invocation and "this" - Yehuda Katz](http://yehudakatz.com/2011/08/11/understanding-javascript-function-invocation-and-this/)
- [JavaScript this - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this)

### Class

JavaScript is a [prototype-based](https://en.wikipedia.org/wiki/Prototype-based_programming) language (whereas Java is [class-based](https://en.wikipedia.org/wiki/Class-based_programming) language, for instance). ES6 has introduced JavaScript classes which are meant to be a syntactic sugar for prototype-based inheritance and **not** a new class-based inheritance model ([ref](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes)).

The word *class* is indeed error prone if you are familiar with classes in other languages. If you do, avoid assuming how JavaScript classes work on this basis and consider it an entirely different notion.

Since this document is not an attempt to teach you the language from the ground up, I will assume you know what prototypes are and how they behave. If you do not, see the external resources listed below the sample code.

#### Samples

Before ES6, prototype syntax:

```js
var Person = function(name, age) {
  this.name = name;
  this.age = age;
}
Person.prototype.stringSentence = function() {
  return "Hello, my name is " + this.name + " and I'm " + this.age;
}
```

With ES6 class syntax:

```js
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  stringSentence() {
    return `Hello, my name is ${this.name} and I am ${this.age}`;
  }
}

const myPerson = new Person("Manu", 23);
console.log(myPerson.age) // 23
console.log(myPerson.stringSentence()) // "Hello, my name is Manu and I'm 23
```

#### External resources

For prototype understanding:

- [Understanding Prototypes in JS - Yehuda Katz](http://yehudakatz.com/2011/08/12/understanding-prototypes-in-javascript/)
- [A plain English guide to JS prototypes - Sebastian Porto](http://sporto.github.io/blog/2013/02/22/a-plain-english-guide-to-javascript-prototypes/)
- [Inheritance and the prototype chain - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain)

For classes understanding:

- [ES6 Classes in Depth - Nicolas Bevacqua](https://ponyfoo.com/articles/es6-classes-in-depth)
- [ES6 Features - Classes](http://es6-features.org/#ClassDefinition)
- [JavaScript Classes - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes)

### `Extends` and `super` keywords

The `extends` keyword is used in class declarations or class expressions to create a class which is a child of another class ([Ref: MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends)). The subclass inherits all the properties of the superclass and additionally can add new properties or modify the inherited ones.

The `super` keyword is used to call functions on an object's parent, including its constructor.

- `super` keyword must be used before the `this` keyword is used in constructor
- Invoking `super()` calls the parent class constructor. If you want to pass some arguments in a class's constructor to its parent's constructor, you call it with `super(arguments)`.
- If the parent class have a method (even static) called `X`, you can use `super.X()` to call it in a child class.

#### Sample Code

```js
class Polygon {
  constructor(height, width) {
    this.name = 'Polygon';
    this.height = height;
    this.width = width;
  }

  getHelloPhrase() {
    return `Hi, I am a ${this.name}`;
  }
}

class Square extends Polygon {
  constructor(length) {
    // Here, it calls the parent class' constructor with lengths
    // provided for the Polygon's width and height
    super(length, length);
    // Note: In derived classes, super() must be called before you
    // can use 'this'. Leaving this out will cause a reference error.
    this.name = 'Square';
    this.length = length;
  }

  getCustomHelloPhrase() {
    const polygonPhrase = super.getHelloPhrase(); // accessing parent method with super.X() syntax
    return `${polygonPhrase} with a length of ${this.length}`;
  }

  get area() {
    return this.height * this.width;
  }
}

const mySquare = new Square(10);
console.log(mySquare.area) // 100
console.log(mySquare.getHelloPhrase()) // 'Hi, I am a Square' -- Square inherits from Polygon and has access to its methods
console.log(mySquare.getCustomHelloPhrase()) // 'Hi, I am a Square with a length of 10'
```

**Note :** If we had tried to use `this` before calling `super()` in Square class, a ReferenceError would have been raised:

```js
class Square extends Polygon {
  constructor(length) {
    this.height; // ReferenceError, super needs to be called first!

    // Here, it calls the parent class' constructor with lengths
    // provided for the Polygon's width and height
    super(length, length);

    // Note: In derived classes, super() must be called before you
    // can use 'this'. Leaving this out will cause a reference error.
    this.name = 'Square';
  }
}
```

#### External Resources

- [Extends - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends)
- [Super operator - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super)
- [Inheritance - MDN](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance)

### Async Await

In addition to [Promises](#promises), there is a new syntax you might encounter to handle asynchronous code named *async / await*.

The purpose of async/await functions is to simplify the behavior of using promises synchronously and to perform some behavior on a group of Promises. Just as Promises are similar to structured callbacks, async/await is similar to combining generators and promises. Async functions *always* return a Promise. ([Ref: MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function))

> **Note :** You must understand what promises are and how they work before trying to understand async / await since they rely on it.

> **Note 2:** [*await* must be used in an *async* function](https://hackernoon.com/6-reasons-why-javascripts-async-await-blows-promises-away-tutorial-c7ec10518dd9#f3f0), which means that you can't use await in the top level of our code since that is not inside an async function.

#### Sample code

```js
async function getGithubUser(username) { // async keyword allows usage of await in the function and means function returns a promise
  const response = await fetch(`https://api.github.com/users/${username}`); // Execution is paused here until the Promise returned by fetch is resolved
  return response.json();
}

getGithubUser('mbeaudru')
  .then(user => console.log(user)) // logging user response - cannot use await syntax since this code isn't in async function
  .catch(err => console.log(err)); // if an error is thrown in our async function, we will catch it here
```

#### Explanation with sample code

*Async / Await* is built on promises but they allow a more imperative style of code.

The *async* operator marks a function as asynchronous and will always return a *Promise*. You can use the *await* operator in an *async* function to pause execution on that line until the returned Promise from the expression either resolves or rejects.

```js
async function myFunc() {
  // we can use await operator because this function is async
  return "hello world";
}

myFunc().then(msg => console.log(msg)) // "hello world" -- myFunc's return value is turned into a promise because of async operator
```

When the *return* statement of an async function is reached, the Promise is fulfilled with the value returned. If an error is thrown inside an async function, the Promise state will turn to *rejected*. If no value is returned from an async function, a Promise is still returned and resolves with no value when execution of the async function is complete.

*await* operator is used to wait for a *Promise* to be fulfilled and can only be used inside an *async* function body. When encountered, the code execution is paused until the promise is fulfilled.

> **Note :** *fetch* is a function that returns a Promise that allows to do an AJAX request

Let's see how we could fetch a github user with promises first:

```js
function getGithubUser(username) {
  return fetch(`https://api.github.com/users/${username}`).then(response => response.json());
}

getGithubUser('mbeaudru')
  .then(user => console.log(user))
  .catch(err => console.log(err));
```

Here's the *async / await* equivalent:

```js
async function getGithubUser(username) { // promise + await keyword usage allowed
  const response = await fetch(`https://api.github.com/users/${username}`); // Execution stops here until fetch promise is fulfilled
  return response.json();
}

getGithubUser('mbeaudru')
  .then(user => console.log(user))
  .catch(err => console.log(err));
```

*async / await* syntax is particularly convenient when you need to chain promises that are interdependent.

For instance, if you need to get a token in order to be able to fetch a blog post on a database and then the author informations:

> **Note :** *await* expressions needs to be wrapped in parentheses to call its resolved value's methods and properties on the same line.

```js
async function fetchPostById(postId) {
  const token = (await fetch('token_url')).json().token;
  const post = (await fetch(`/posts/${postId}?token=${token}`)).json();
  const author = (await fetch(`/users/${post.authorId}`)).json();

  post.author = author;
  return post;
}

fetchPostById('gzIrzeo64')
  .then(post => console.log(post))
  .catch(err => console.log(err));
```

##### Error handling

Unless we add *try / catch* blocks around *await* expressions, uncaught exceptions – regardless of whether they were thrown in the body of your *async* function or while it’s suspended during *await* – will reject the promise returned by the *async* function. Using the `throw` statement in an async function is the same as returning a Promise that rejects. [(Ref: PonyFoo)](https://ponyfoo.com/articles/understanding-javascript-async-await#error-handling).

> **Note :** Promises behave the same!

With promises, here is how you would handle the error chain:

```js
function getUser() { // This promise will be rejected!
  return new Promise((res, rej) => rej("User not found !"));
}

function getAvatarByUsername(userId) {
  return getUser(userId).then(user => user.avatar);
}

function getUserAvatar(username) {
  return getAvatarByUsername(username).then(avatar => ({ username, avatar }));
}

getUserAvatar('mbeaudru')
  .then(res => console.log(res))
  .catch(err => console.log(err)); // "User not found !"
```

The equivalent with *async / await*:

```js
async function getUser() { // The returned promise will be rejected!
  throw "User not found !";
}

async function getAvatarByUsername(userId) => {
  const user = await getUser(userId);
  return user.avatar;
}

async function getUserAvatar(username) {
  var avatar = await getAvatarByUsername(username);
  return { username, avatar };
}

getUserAvatar('mbeaudru')
  .then(res => console.log(res))
  .catch(err => console.log(err)); // "User not found !"
```

#### External resources

- [Async/Await - JavaScript.Info](https://javascript.info/async-await)
- [ES7 Async/Await](http://rossboucher.com/await/#/)
- [6 Reasons Why JavaScript’s Async/Await Blows Promises Away](https://hackernoon.com/6-reasons-why-javascripts-async-await-blows-promises-away-tutorial-c7ec10518dd9)
- [JavaScript awaits](https://dev.to/kayis/javascript-awaits)
- [Using Async Await in Express with Node 8](https://medium.com/@Abazhenov/using-async-await-in-express-with-node-8-b8af872c0016)
- [Async Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function)
- [Await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await)
- [Using async / await in express with node 8](https://medium.com/@Abazhenov/using-async-await-in-express-with-node-8-b8af872c0016)

### Truthy / Falsy

In JavaScript, a truthy or falsy value is a value that is being casted into a boolean when evaluated in a boolean context. An example of boolean context would be the evaluation of an ```if``` condition:

Every value will be casted to ```true``` unless they are equal to:

- ```false```
- ```0```
- ```""``` (empty string)
- ```null```
- ```undefined```
- ```NaN```

Here are examples of *boolean context*:

- ```if``` condition evaluation

```js
if (myVar) {}
```

```myVar``` can be any [first-class citizen](https://en.wikipedia.org/wiki/First-class_citizen) (variable, function, boolean) but it will be casted into a boolean because it's evaluated in a boolean context.

- After logical **NOT** ```!``` operator

This operator returns false if its single operand can be converted to true; otherwise, returns true.

```js
!0 // true -- 0 is falsy so it returns true
!!0 // false -- 0 is falsy so !0 returns true so !(!0) returns false
!!"" // false -- empty string is falsy so NOT (NOT false) equals false
```

- With the *Boolean* object constructor

```js
new Boolean(0) // false
new Boolean(1) // true
```

- In a ternary evaluation

```js
myVar ? "truthy" : "falsy"
```

myVar is evaluated in a boolean context.

Be careful when comparing 2 values. The object values (that should be cast to true) is **not** being casted to Boolean but it forced to convert into a primitive value one using [ToPrimitives specification](http://javascript.info/object-toprimitive). Internally, when an object is compared to Boolean value like `[] == true`, it does `[].toString() == true` so...

```js
let a = [] == true // a is false since [].toString() give "" back.
let b = [1] == true // b is true since [1].toString() give "1" back.
let c = [2] == true // c is false since [2].toString() give "2" back.
```

#### External resources

- [Truthy (MDN)](https://developer.mozilla.org/en-US/docs/Glossary/Truthy)
- [Falsy (MDN)](https://developer.mozilla.org/en-US/docs/Glossary/Falsy)
- [Truthy and Falsy values in JS - Josh Clanton](http://adripofjavascript.com/blog/drips/truthy-and-falsy-values-in-javascript.html)

### Anamorphisms and Catamorphisms

#### Anamorphisms

Anamorphisms are functions that map from some object to a more complex structure containing the type of the object. It is the process of *unfolding* a simple structure into a more complex one. Consider unfolding an integer to a list of integers. The integer is our initial object and the list of integers is the more complex structure.

**Sample code**

```js
function downToOne(n) {
  const list = [];

  for (let i = n; i > 0; --i) {
    list.push(i);
  }

  return list;
}

downToOne(5)
  //=> [ 5, 4, 3, 2, 1 ]
```

#### Catamorphisms

Catamorphisms are the opposite of Anamorphisms, in that they take objects of more complex structure and *fold* them into simpler structures. Take the following example `product` which take a list of integers and returns a single integer.

**Sample code**

```js
function product(list) {
  let product = 1;

  for (const n of list) {
    product = product * n;
  }

  return product;
}

product(downToOne(5)) // 120
```

#### External resources

* [Anamorphisms in JavaScript](http://raganwald.com/2016/11/30/anamorphisms-in-javascript.html)
* [Anamorphism](https://en.wikipedia.org/wiki/Anamorphism)
* [Catamorphism](https://en.wikipedia.org/wiki/Catamorphism)

### Generators

Another way to write the `downToOne` function is to use a Generator. To instantiate a `Generator` object, one must use the `function *` declaration. Generators are functions that can be exited and later re-entered with its context (variable bindings) saved across re-entrances.

For example, the `downToOne` function above can be rewritten as:

```js
function * downToOne(n) {
  for (let i = n; i > 0; --i) {
    yield i;
  }
}

[...downToOne(5)] // [ 5, 4, 3, 2, 1 ]
```

Generators return an iterable object. When the iterator's `next()` function is called, it is executed until the first `yield` expression, which specifies the value to be returned from the iterator or with `yield*`, which delegates to another generator function. When a `return` expression is called in the generator, it will mark the generator as done and pass back as the return value. Further calls to `next()` will not return any new values.

**Sample code**

```js
// Yield Example
function * idMaker() {
  var index = 0;
  while (index < 2) {
    yield index;
    index = index + 1;
  }
}

var gen = idMaker();

gen.next().value; // 0
gen.next().value; // 1
gen.next().value; // undefined
```

The `yield*` expression enables a generator to call another generator function during iteration.

```js
// Yield * Example
function * genB(i) {
  yield i + 1;
  yield i + 2;
  yield i + 3;
}

function * genA(i) {
  yield i;
  yield* genB(i);
  yield i + 10;
}

var gen = genA(10);

gen.next().value; // 10
gen.next().value; // 11
gen.next().value; // 12
gen.next().value; // 13
gen.next().value; // 20
```

```js
// Generator Return Example
function* yieldAndReturn() {
  yield "Y";
  return "R";
  yield "unreachable";
}

var gen = yieldAndReturn()
gen.next(); // { value: "Y", done: false }
gen.next(); // { value: "R", done: true }
gen.next(); // { value: undefined, done: true }
```

#### External resources

* [Mozilla MDN Web Docs, Iterators and Generators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators#Generators)

### Static Methods

#### Short explanation

The `static` keyword is used in classes to declare static methods. Static methods are functions in a class that belongs to the class object and are not available to any instance of that class.

#### Sample code

```js
class Repo {
  static getName() {
    return "Repo name is modern-js-cheatsheet"
  }
}

// Note that we did not have to create an instance of the Repo class
console.log(Repo.getName()) // Repo name is modern-js-cheatsheet

let r = new Repo();
console.log(r.getName()) // Uncaught TypeError: r.getName is not a function
```

#### Detailed explanation

Static methods can be called within another static method by using the `this` keyword, this doesn't work for non-static methods though. Non-static methods cannot directly access static methods using the `this` keyword.

##### Calling other static methods from a static method.

To call a static method from another static method, the `this` keyword can be used like so;

```js
class Repo {
  static getName() {
    return "Repo name is modern-js-cheatsheet"
  }

  static modifyName() {
    return this.getName() + '-added-this'
  }
}

console.log(Repo.modifyName()) // Repo name is modern-js-cheatsheet-added-this
```

##### Calling static methods from non-static methods.

Non-static methods can call static methods in 2 ways;
1. ###### Using the class name.

To get access to a static method from a non-static method we use the class name and call the static method like a property. e.g `ClassName.StaticMethodName`

```js
class Repo {
  static getName() {
    return "Repo name is modern-js-cheatsheet"
  }

  useName() {
    return Repo.getName() + ' and it contains some really important stuff'
  }
}

// we need to instantiate the class to use non-static methods
let r = new Repo()
console.log(r.useName()) // Repo name is modern-js-cheatsheet and it contains some really important stuff
```

2. ###### Using the constructor

Static methods can be called as properties on the constructor object.

```js
class Repo {
  static getName() {
    return "Repo name is modern-js-cheatsheet"
  }

  useName() {
    // Calls the static method as a property of the constructor
    return this.constructor.getName() + ' and it contains some really important stuff'
  }
}

// we need to instantiate the class to use non-static methods
let r = new Repo()
console.log(r.useName()) // Repo name is modern-js-cheatsheet and it contains some really important stuff
```

#### External resources
- [static keyword- MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static)
- [Static Methods- Javascript.info](https://javascript.info/class#static-methods)
- [Static Members in ES6- OdeToCode](http://odetocode.com/blogs/scott/archive/2015/02/02/static-members-in-es6.aspx)

## Glossary

### <a name="scope_def"></a> Scope

The context in which values and expressions are "visible," or can be referenced. If a variable or other expression is not "in the current scope," then it is unavailable for use.

Source: [MDN](https://developer.mozilla.org/en-US/docs/Glossary/Scope)

### <a name="mutation_def"></a> Variable mutation

A variable is said to have been mutated when its initial value has changed afterward.

```js
var myArray = [];
myArray.push("firstEl") // myArray is being mutated
```

A variable is said to be *immutable* if it can't be mutated.

[Check MDN Mutable article](https://developer.mozilla.org/en-US/docs/Glossary/Mutable) for more details.


================================================
FILE: _config.yml
================================================
theme: jekyll-theme-cayman
title: Modern JS Cheatsheet


================================================
FILE: translations/de-DE.md
================================================
# Modern JavaScript Cheatsheet

![Modern JavaScript cheatsheet](https://i.imgur.com/aexPxMb.png)
<sub>Bildnachweis: [Ahmad Awais ⚡️](https://github.com/ahmadawais)</sub>

> Wenn dir dieser Inhalt gefällt, kannst du mich anpingen oder mir auf Twitter folgen :+1:

[![Tweet for help](https://img.shields.io/twitter/follow/mbeaudru?label=Tweet%20%40mbeaudru&style=social)](https://twitter.com/mbeaudru/)

## Einführung

### Motivation

Dieses Dokument ist ein Spickzettel für JavaScript, das du häufig in modernen Projekten und den meisten aktuellen Beispielcodes antreffen wirst.

Dieser Leitfaden ist nicht dazu gedacht, dir JavaScript von Grund auf beizubringen, sondern ist eine Hilfe für Entwickler mit grundlegendem Wissen, die Schwierigkeiten haben, sich mit modernen Codebasen vertraut zu machen (oder sagen wir, React zu lernen), aufgrund der in JavaScript verwendeten Konzepte.

Außerdem werde ich manchmal persönliche Tipps geben, die diskutierbar sein könnten, aber ich werde darauf hinweisen, dass es eine persönliche Empfehlung ist, wenn ich das tue.

> **Hinweis:** Die meisten der hier eingeführten Konzepte stammen aus einem JavaScript Sprachupdate (ES2015, oft als ES6 bezeichnet). Neue Funktionen, die durch dieses Update hinzugefügt wurden, findest du [hier](http://es6-features.org); sehr gut gemacht.

### Ergänzende Ressourcen

Wenn du Schwierigkeiten hast, eine Vorstellung zu verstehen, schlage ich vor, dass du nach Antworten in den folgenden Ressourcen suchst:

- [MDN (Mozilla Developer Network)](https://developer.mozilla.org/de/search?q=)
- [You don't know JS (Buch)](https://github.com/getify/You-Dont-Know-JS)
- [Eloquent JavaScript (Buch)](https://eloquentjavascript.net)
- [Douglas Crockford's Blog](https://www.crockford.com/javascript/)
- [ES6 Features mit Beispielen](http://es6-features.org)
- [Wes Bos Blog (ES6)](https://wesbos.com/javascript)
- [Javascript Grundlagen für Anfänger](https://www.udacity.com/course/javascript-basics--ud804) - ein kostenloser Udacity-Kurs
- [Reddit (JavaScript)](https://www.reddit.com/r/javascript/)
- [Google](https://www.google.com/) um spezifische Blogs und Ressourcen zu finden
- [StackOverflow](https://stackoverflow.com/questions/tagged/javascript)

## Inhaltsverzeichnis

- [Modern JavaScript Cheatsheet](#modern-javascript-cheatsheet)
  * [Einführung](#einführung)
    + [Motivation](#motivation)
    + [Ergänzende Ressourcen](#ergänzende-ressourcen)
  * [Inhaltsverzeichnis](#inhaltsverzeichnis)
  * [Begriffe](#begriffe)
    + [Variablendeklaration: var, const, let](#variablendeklaration-var-const-let)
      - [Kurze Erklärung](#kurze-erklärung)
      - [Beispielcode](#beispielcode)
      - [Ausführliche Erklärung](#ausführliche-erklärung)
      - [Externe Ressource](#externe-ressource)
    + [Pfeilfunktion](#-pfeilfunktion)
      - [Beispielcode](#beispielcode-1)
      - [Ausführliche Erklärung](#ausführliche-erklärung-1)
        * [Prägnanz](#prägnanz)
        * [*this* Referenz](#this-referenz)
      - [Nützliche Ressourcen](#nützliche-ressourcen)
    + [Standardparameterwert für Funktionen](#standardparameterwert-für-funktionen)
      - [Externe Ressource](#externe-ressource-1)
    + [Destrukturierung von Objekten und Arrays](#destrukturierung-von-objekten-und-arrays)
      - [Erklärung mit Beispielcode](#erklärung-mit-beispielcode)
      - [Nützliche Ressourcen](#nützliche-ressourcen-1)
    + [Array-Methoden - map / filter / reduce](#array-methoden---map--filter--reduce--find)
      - [Beispielcode](#beispielcode-2)
      - [Erklärung](#erklärung)
        * [Array.prototype.map()](#arrayprototypemap)
        * [Array.prototype.filter()](#arrayprototypefilter)
        * [Array.prototype.reduce()](#arrayprototypereduce)
        * [Array.prototype.find()](#arrayprototypefind)
      - [Externe Ressource](#externe-ressource-2)
    + [Spread-Operator "..."](#spread-operator-)
      - [Beispielcode](#beispielcode-3)
      - [Erklärung](#erklärung-1)
        * [In Iterables (wie Arrays)](#in-iterables-wie-arrays)
        * [Funktionsrestparameter](#funktionsrestparameter)
        * [Objekteigenschaften ausbreiten](#objekteigenschaften-ausbreiten)
      - [Externe Ressourcen](#externe-ressourcen)
    + [Objekteigenschaften Kurzschreibweise](#objekteigenschaften-kurzschreibweise)
      - [Erklärung](#erklärung-2)
      - [Externe Ressourcen](#externe-ressourcen-1)
    + [Promises](#promises)
      - [Beispielcode](#beispielcode-4)
      - [Erklärung](#erklärung-3)
        * [Das Promise erstellen](#das-promise-erstellen)
        * [Verwendung von Promise-Handlern](#verwendung-von-promise-handlern)
      - [Externe Ressourcen](#externe-ressourcen-2)
    + [Template Literale](#template-literale)
      - [Beispielcode](#beispielcode-5)
      - [Externe Ressourcen](#externe-ressourcen-3)
    + [Tagged Template Literale](#tagged-template-literale)
      - [Externe Ressourcen](#externe-ressourcen-4)
    + [Imports / Exports](#imports--exports)
      - [Erklärung mit Beispielcode](#erklärung-mit-beispielcode-1)
        * [Benannte Exports](#benannte-exports)
        * [Standardimport / export](#standardimport--export)
      - [Externe Ressourcen](#externe-ressourcen-5)
    + [JavaScript *this*](#-javascript-this)
      - [Externe Ressourcen](#externe-ressourcen-6)
    + [Klasse](#klasse)
      - [Beispiele](#beispiele)
      - [Externe Ressourcen](#externe-ressourcen-7)
    + [Extends und super](#extends-und-super)
      - [Beispielcode](#beispielcode-6)
      - [Externe Ressourcen](#externe-ressourcen-8)
    + [Async Await](#async-await)
      - [Beispielcode](#beispielcode-7)
      - [Erklärung mit Beispielcode](#erklärung-mit-beispielcode-2)
      - [Fehlerbehandlung](#fehlerbehandlung)
      - [Externe Ressourcen](#externe-ressourcen-9)
    + [Truthy / Falsy](#truthy--falsy)
      - [Externe Ressourcen](#externe-ressourcen-10)
    + [Anamorphismen / Katamorphismen](#anamorphismen-und-katamorphismen)
      - [Anamorphismen](#anamorphismen)
      - [Katamorphismen](#katamorphismen)
      - [Externe Ressourcen](#externe-ressourcen-11)
    + [Generatoren](#generatoren)
      - [Externe Ressourcen](#externe-ressourcen-12)
    + [Statische Methoden](#statische-methoden)
      - [Kurze Erklärung](#kurze-erklärung-1)
      - [Beispielcode](#beispielcode-8)
      - [Ausführliche Erklärung](#ausführliche-erklärung-2)
        * [Andere statische Methoden aus einer statischen Methode aufrufen](#andere-statische-methoden-aus-einer-statischen-methode-aufrufen)
        * [Statische Methoden aus nicht-statischen Methoden aufrufen](#statische-methoden-aus-nicht-statischen-methoden-aufrufen)
      - [Externe Ressourcen](#externe-ressourcen-13)
  * [Glossar](#glossar)
    + [Scope](#-scope)
    + [Variablenmutation](#-variablenmutation)

## Begriffe

### Variablendeklaration: var, const, let

In JavaScript gibt es drei Schlüsselwörter, um eine Variable zu deklarieren, und jedes hat seine Unterschiede. Diese Schlüsselwörter sind ```var```, ```let``` und ```const```.

#### Kurze Erklärung

Variablen, die mit dem Schlüsselwort ```const``` deklariert sind, können nicht neu zugewiesen werden, während ```let``` und ```var``` neu zugewiesen werden können.

Ich empfehle, deine Variablen standardmäßig mit ```const``` zu deklarieren, aber mit ```let```, wenn es eine Variable ist, die du später *mutieren* oder neu zuweisen musst.

<table>
  <tr>
    <th></th>
    <th>Scope</th>
    <th>Neu zuzuweisend</th>
    <th>Veränderbar</th>
   <th><a href="#tdz_sample">Temporal Dead Zone</a></th>
  </tr>
  <tr>
    <th>const</th>
    <td>Block</td>
    <td>Nein</td>
    <td><a href="#const_mutable_sample">Ja</a></td>
    <td>Ja</td>
  </tr>
  <tr>
    <th>let</th>
    <td>Block</td>
    <td>Ja</td>
    <td>Ja</td>
    <td>Ja</td>
  </tr>
   <tr>
    <th>var</th>
    <td>Funktion</td>
    <td>Ja</td>
    <td>Ja</td>
    <td>Nein</td>
  </tr>
</table>

#### Beispielcode

```javascript
const person = "Nick";
person = "John" // Wird einen Fehler werfen, person kann nicht neu zugewiesen werden
```

```javascript
let person = "Nick";
person = "John";
console.log(person) // "John", Neu-Zuweisung ist erlaubt mit let
```

#### Ausführliche Erklärung

Der [*Scope*](#scope_def) einer Variable bedeutet grob "wo ist diese Variable im Code verfügbar".

##### var

```var``` deklarierte Variablen sind *funktionsumfänglich*, was bedeutet, dass, wenn eine Variable in einer Funktion erstellt wird, alles in dieser Funktion Zugriff auf diese Variable hat. Außerdem kann eine *funktionsumfängliche* Variable, die in einer Funktion erstellt wurde, nicht außerhalb dieser Funktion zugegriffen werden.

Ich empfehle dir, es dir so vorzustellen, als ob eine *X-umfängliche* Variable bedeutet, dass diese Variable eine Eigenschaft von X ist.

```javascript
function myFunction() {
  var myVar = "Nick";
  console.log(myVar); // "Nick" - myVar ist innerhalb der Funktion zugänglich
}
console.log(myVar); // Wirft einen ReferenceError, myVar ist außerhalb der Funktion nicht zugänglich.
```

Fokussieren wir uns immer noch auf den Variablenscope, hier ist ein subtileres Beispiel:

```javascript
function myFunction() {
  var myVar = "Nick";
  if (true) {
    var myVar = "John";
    console.log(myVar); // "John"
    // eigentlich, da myVar funktionsumfänglich ist, haben wir einfach den vorherigen myVar-Wert "Nick" durch "John" ersetzt
  }
  console.log(myVar); // "John" - sieh, wie die Anweisungen im if-Block diesen Wert beeinflusst haben
}
console.log(myVar); // Wirft einen ReferenceError, myVar ist außerhalb der Funktion nicht zugänglich.
```

Außerdem werden *var* deklarierte Variablen zum Anfang des Scopes bei der Ausführung verschoben. Dies nennt man [var hoisting](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Statements/var#var_hoisting).

Dieser Codeabschnitt:

```js
console.log(myVar) // undefined -- kein Fehler geworfen
var myVar = 2;
```

wird bei der Ausführung so verstanden:

```js
var myVar;
console.log(myVar) // undefined -- kein Fehler geworfen
myVar = 2;
```

##### let

```var``` und ```let ``` sind ungefähr gleich, aber bei ```let``` deklarierte Variablen

- haben einen *Block-Scope*
- sind **nicht** zugänglich, bevor sie zugewiesen werden
- können nicht im gleichen Scope neu deklariert werden

Lasst uns die Auswirkung der Block-Scoping anhand unseres vorherigen Beispiels sehen:

```javascript
function myFunction() {
  let myVar = "Nick";
  if (true) {
    let myVar = "John";
    console.log(myVar); // "John"
    // eigentlich, da myVar einen Block-Scope hat, haben wir gerade eine neue Variable myVar erstellt.
    // Diese Variable ist außerhalb dieses Blocks nicht zugänglich und völlig unabhängig
    // von der ersten erstellten myVar!
  }
  console.log(myVar); // "Nick", sieh, wie die Anweisungen im if-Block diesen Wert NICHT beeinflusst haben
}
console.log(myVar); // Wirft einen ReferenceError, myVar ist außerhalb der Funktion nicht zugänglich.
```

<a name="tdz_sample"></a> Nun, was es für *let* (und *const*) Variablen bedeutet, nicht zugänglich zu sein, bevor sie zugewiesen werden:

```js
console.log(myVar) // wirft einen ReferenceError !
let myVar = 2;
```

Im Gegensatz zu *var* Variablen, wenn du versuchst, eine *let* oder *const* Variable zu lesen oder zu schreiben, bevor sie zugewiesen sind, wird ein Fehler ausgelöst. Dieses Phänomen wird oft [*Temporal Dead Zone*](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Statements/let#Temporal_Dead_Zone_and_errors_with_let) oder *TDZ* genannt.

> **Hinweis:** Technisch gesehen werden *let* und *const* Variablendeklarationen auch gehoistet, aber nicht ihre Zuweisung. Da sie so gemacht sind, dass sie nicht vor der Zuweisung verwendet werden können, fühlt es sich intuitiv an, als ob es kein Hoisting gäbe, aber es gibt es. Finde mehr in [dieser sehr detaillierten Erklärung](http://jsrocks.org/2015/01/temporal-dead-zone-tdz-demystified) heraus, wenn du mehr wissen möchtest.

Außerdem kannst du eine *let* Variable nicht neu deklarieren:

```js
let myVar = 2;
let myVar = 3; // Wirft einen SyntaxError
```

##### const

Mit *const* deklarierte Variablen verhalten sich wie *let*-Variablen, können aber auch nicht neu zugewiesen werden.

Zusammenfassend können *const*-Variablen:

- haben einen *Block-Scope*
- sind nicht zugänglich bevor sie zugewiesen werden
- können nicht im gleichen Scope neu deklariert werden
- können nicht neu zugewiesen werden

```js
const myVar = "Nick";
myVar = "John" // Wirft einen Fehler, Neuzuweisung ist nicht erlaubt
```

```js
const myVar = "Nick";
const myVar = "John" // Wirft einen Fehler, Neudeklarierung ist nicht erlaubt
```

<a name="const_mutable_sample"></a> Aber es gibt eine Feinheit: ```const``` Variablen sind nicht [**unveränderbar**](#mutation_def)! Konkret bedeutet das, dass *Objekt*- und *Array*-```const``` deklarierte Variablen **verändert** werden können.

Für Objekte:
```js
const person = {
  name: 'Nick'
};
person.name = 'John' // das funktioniert! Die Variable person wird nicht komplett neu zugewiesen, sondern verändert
console.log(person.name) // "John"
person = "Sandra" // wirft einen Fehler, da Neu-Zuweisung nicht erlaubt ist für const deklarierte Variablen
```

Für Arrays:
```js
const person = [];
person.push('John'); // das funktioniert! Die Variable person wird nicht komplett neu zugewiesen, sondern verändert
console.log(person[0]) // "John"
person = ["Nick"] // wirft einen Fehler, da Neu-Zuweisung nicht erlaubt ist für const deklarierte Variablen
```

#### Externe Ressource

- [Wie let und const in JavaScript skopiert werden - WesBos](http://wesbos.com/javascript-scoping/)
- [Temporal Dead Zone (TDZ) Demystifiziert](http://jsrocks.org/2015/01/temporal-dead-zone-tdz-demystified)

### <a name="arrow_func_concept"></a> Pfeilfunktion

Das ES6 JavaScript Update hat *Pfeilfunktionen* eingeführt, die eine weitere Methode darstellen, Funktionen zu deklarieren und zu verwenden. Hier sind die Vorteile, die sie mitbringen:

- Kürzerer Code
- *this* wird aus der Umgebung übernommen
- implizite Rückgabe

#### Beispielcode

- Kürze und implizite Rückgabe

```js
function double(x) { return x * 2; } // Traditioneller Weg
console.log(double(2)) // 4
```

```js
const double = x => x * 2; // Gleiche Funktion als Pfeilfunktion mit impliziter Rückgabe geschrieben
console.log(double(2)) // 4
```

- *this*-Referenz

In einer Pfeilfunktion ist *this* gleich dem *this*-Wert des umschließenden Ausführungskontextes. Im Grunde musst du mit Pfeilfunktionen nicht mehr den Trick "that = this" anwenden, bevor du eine Funktion in einer Funktion aufrufst.

```js
function myFunc() {
  this.myVar = 0;
  setTimeout(() => {
    this.myVar++;
    console.log(this.myVar) // 1
  }, 0);
}
```

#### Ausführliche Erklärung

##### Prägnanz

Pfeilfunktionen sind in vielerlei Hinsicht prägnanter als traditionelle Funktionen. Lass uns alle möglichen Fälle überprüfen:

- Implizite vs. explizite Rückgabe

Eine **explizite Rückgabe** ist eine Funktion, in deren Körper das Schlüsselwort *return* verwendet wird.

```js
  function double(x) {
    return x * 2; // diese Funktion gibt explizit x * 2 zurück, das Schlüsselwort *return* wird verwendet
  }
```

Auf traditionelle Weise geschriebene Funktionen hatten immer eine explizite Rückgabe. Aber mit Pfeilfunktionen kannst du eine *implizite Rückgabe* durchführen, was bedeutet, dass du das Schlüsselwort *return* nicht verwenden musst, um einen Wert zurückzugeben.

```js
  const double = (x) => {
    return x * 2; // Hier explizite Rückgabe
  }
```

Da diese Funktion nur etwas zurückgibt (keine Anweisungen vor dem Schlüsselwort *return*), können wir eine implizite Rückgabe durchführen.

```js
  const double = (x) => x * 2; // Korrekt, gibt x*2 zurück
```

Um dies zu tun, müssen wir nur die **Klammern** und das Schlüsselwort **return** entfernen. Daher wird sie als *implizite* Rückgabe bezeichnet, das Schlüsselwort *return* ist nicht vorhanden, aber diese Funktion wird tatsächlich ```x * 2``` zurückgeben.

> **Hinweis:** Wenn deine Funktion keinen Wert zurückgibt (mit *Nebenwirkungen*), führt sie weder eine explizite noch eine implizite Rückgabe durch.

Außerdem, wenn du ein *Objekt* implizit zurückgeben möchtest, **musst du es in Klammern setzen**, da es sonst zu Konflikten mit den Blockklammern kommen würde:

```js
const getPerson = () => ({ name: "Nick", age: 24 })
console.log(getPerson()) // { name: "Nick", age: 24 } -- Objekt wird implizit durch Pfeilfunktion zurückgegeben
```

- Nur ein Argument

Wenn deine Funktion nur einen Parameter hat, kannst du die Klammern um ihn herum weglassen. Wenn wir den oben genannten *double*-Code wieder aufgreifen:

```js
  const double = (x) => x * 2; // diese Pfeilfunktion nimmt nur einen Parameter entgegen
```

Klammern um den Parameter können vermieden werden:

```js
  const double = x => x * 2; // diese Pfeilfunktion nimmt nur einen Parameter entgegen
```

- Keine Argumente

Wenn einer Pfeilfunktion kein Argument übergeben wird, musst du Klammern angeben, sonst ist die Syntax nicht gültig.

```js
  () => { // Klammern werden angegeben, alles ist in Ordnung
    const x = 2;
    return x;
  }
```

```js
  => { // Keine Klammern, das wird nicht funktionieren!
    const x = 2;
    return x;
  }
```

##### *this*-Referenz

Um diese Nuance, die mit Pfeilfunktionen eingeführt wurde, zu verstehen, muss du wissen, wie [this](#this_def) sich in JavaScript verhält.

In einer Pfeilfunktion ist *this* gleich dem *this*-Wert des umschließenden Ausführungskontextes. Das bedeutet, dass eine Pfeilfunktion kein neues *this* erstellt, sondern es stattdessen aus seiner Umgebung übernimmt.

Ohne Pfeilfunktion, wenn du in einer Funktion innerhalb einer Funktion auf eine Variable von *this* zugreifen wolltest, musstest du den Trick *that = this* oder *self = this* anwenden.

Zum Beispiel beim Verwenden der setTimeout-Funktion innerhalb von myFunc:

```js
function myFunc() {
  this.myVar = 0;
  var that = this; // that = this Trick
  setTimeout(
    function() { // Ein neues *this* wird in diesem Funktionsbereich erstellt
      that.myVar++;
      console.log(that.myVar) // 1

      console.log(this.myVar) // undefiniert -- siehe Funktionsdeklaration oben
    },
    0
  );
}
```

Aber mit Pfeilfunktion wird *this* aus seiner Umgebung übernommen:

```js
function myFunc() {
  this.myVar = 0;
  setTimeout(
    () => { // this wird aus der Umgebung übernommen, was hier myFunc bedeutet
      this.myVar++;
      console.log(this.myVar) // 1
    },
    0
  );
}
```

#### Nützliche Ressourcen

- [Einführung in Pfeilfunktionen - WesBos](http://wesbos.com/arrow-functions/)
- [JavaScript Pfeilfunktion - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)
- [Pfeilfunktion und lexikalisches *this*](https://hackernoon.com/javascript-es6-arrow-functions-and-lexical-this-f2a3e2a5e8c4)

### Standardparameterwert für Funktionen

Ab dem ES2015 JavaScript Update kannst du deinen Funktionsparametern Standardwerte zuweisen, indem du folgende Syntax verwendest:

```js
function myFunc(x = 10) {
  return x;
}
console.log(myFunc()) // 10 -- kein Wert wird übergeben, daher wird dem x in myFunc der Standardwert 10 zugewiesen
console.log(myFunc(5)) // 5 -- ein Wert wird übergeben, daher ist x gleich 5 in myFunc

console.log(myFunc(undefined)) // 10 -- der Wert undefined wird übergeben, daher wird der Standardwert dem x zugewiesen
console.log(myFunc(null)) // null -- ein Wert (null) wird übergeben, siehe unten für weitere Details
```

Der Standardparameter wird in zwei und nur zwei Situationen angewendet:

- Kein Parameter übergeben
- *undefined* Parameter übergeben

Anders ausgedrückt, wenn du *null* übergibst, wird der Standardparameter **nicht angewendet**.

> **Hinweis:** Die Zuweisung eines Standardwerts kann auch mit destrukturierten Parametern verwendet werden (siehe nächste Notion, um ein Beispiel zu sehen)

#### Externe Ressource

- [Standardparameterwert - ES6 Features](http://es6-features.org/#DefaultParameterValues)
- [Standardparameter - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters)

### Destrukturierung von Objekten und Arrays

*Destrukturierung* ist eine praktische Methode, neue Variablen zu erstellen, indem einige Werte aus in Objekten oder Arrays gespeicherten Daten extrahiert werden.

Um nur einige Anwendungsfälle zu nennen, kann die *Destrukturierung* verwendet werden, um Funktionsparameter oder *this.props* in React-Projekten zu destrukturieren.

#### Erklärung mit Beispielcode

- Objekt

Betrachten wir das folgende Objekt für alle Beispiele:

```js
const person = {
  firstName: "Nick",
  lastName: "Anderson",
  age: 35,
  sex: "M"
}
```

Ohne Destrukturierung

```js
const first = person.firstName;
const age = person.age;
const city = person.city || "Paris";
```

Mit Destrukturierung, alles in einer Zeile:

```js
const { firstName: first, age, city = "Paris" } = person; // Das war's !

console.log(age) // 35 -- Eine neue Variable age wird erstellt und ist gleich person.age
console.log(first) // "Nick" -- Eine neue Variable first wird erstellt und ist gleich person.firstName
console.log(firstName) // ReferenceError -- person.firstName existiert, ABER die neu erstellte Variable ist als first benannt
console.log(city) // "Paris" -- Eine neue Variable city wird erstellt und da person.city undefiniert ist, ist city gleich dem bereitgestellten Standardwert "Paris".
```

**Hinweis:** In ```const { age } = person;``` werden die Klammern nach dem *const*-Schlüsselwort nicht verwendet, um ein Objekt oder einen Block zu deklarieren, sondern es ist die *Destrukturierungssyntax*.

- Funktionsparameter

*Destrukturierung* wird häufig verwendet, um Objektparameter in Funktionen zu destrukturieren.

Ohne Destrukturierung

```js
function joinFirstLastName(person) {
  const firstName = person.firstName;
  const lastName = person.lastName;
  return firstName + '-' + lastName;
}

joinFirstLastName(person); // "Nick-Anderson"
```

Bei der Destrukturierung des Objektparameters *person* erhalten wir eine präzisere Funktion:

```js
function joinFirstLastName({ firstName, lastName }) { // wir erstellen Variablen firstName und lastName durch Destrukturierung des person-Parameters
  return firstName + '-' + lastName;
}

joinFirstLastName(person); // "Nick-Anderson"
```

Destrukturierung ist noch angenehmer mit [Pfeilfunktionen](#arrow_func_concept) zu verwenden:

```js
const joinFirstLastName = ({ firstName, lastName }) => firstName + '-' + lastName;

joinFirstLastName(person); // "Nick-Anderson"
```

- Array

Betrachten wir das folgende Array:

```js
const myArray = ["a", "b", "c"];
```

Ohne Destrukturierung

```js
const x = myArray[0];
const y = myArray[1];
```

Mit Destrukturierung

```js
const [x, y] = myArray; // Das war's !

console.log(x) // "a"
console.log(y) // "b"
```

#### Nützliche Ressourcen

- [ES6 Features - Destrukturierende Zuweisung](http://es6-features.org/#ArrayMatching)
- [Objektdestrukturierung - WesBos](http://wesbos.com/destructuring-objects/)
- [ExploringJS - Destrukturierung](http://exploringjs.com/es6/ch_destructuring.html)

### Array-Methoden - map / filter / reduce / find

*Map*, *filter*, *reduce* und *find* sind Array-Methoden, die aus einem Programmierparadigma namens [*funktionale Programmierung*](https://medium.com/javascript-scene/master-the-javascript-interview-what-is-functional-programming-7f218c68b3a0) stammen.

Zusammengefasst:

- **Array.prototype.map()** nimmt ein Array, führt eine Operation auf seinen Elementen durch und gibt ein Array mit den transformierten Elementen zurück.
- **Array.prototype.filter()** nimmt ein Array, entscheidet elementweise, ob es dieses behalten will oder nicht, und gibt ein Array nur mit den behaltenen Elementen zurück.
- **Array.prototype.reduce()** nimmt ein Array und aggregiert die Elemente zu einem einzelnen Wert (der zurückgegeben wird).
- **Array.prototype.find()** nimmt ein Array und gibt das erste Element zurück, das die bereitgestellte Bedingung erfüllt.

Ich empfehle, sie so oft wie möglich zu verwenden, indem du den Prinzipien der funktionalen Programmierung folgst, da sie zusammensetzbar, prägnant und elegant sind.

Mit diesen vier Methoden kannst du in den meisten Situationen die Verwendung von *for* und *forEach* Schleifen vermeiden. Wenn du versucht bist, eine *for*-Schleife zu machen, versuche es mit *map*, *filter*, *reduce* und *find* zusammengesetzt. Es könnte anfangs schwierig sein, da es dich zwingt, eine neue Denkweise zu erlernen, aber sobald du es beherrschst, wird alles einfacher.

#### Beispielcode

```js
const numbers = [0, 1, 2, 3, 4, 5, 6];
const doubledNumbers = numbers.map(n => n * 2); // [0, 2, 4, 6, 8, 10, 12]
const evenNumbers = numbers.filter(n => n % 2 === 0); // [0, 2, 4, 6]
const sum = numbers.reduce((prev, next) => prev + next, 0); // 21
const greaterThanFour = numbers.find((n) => n>4); // 5
```

Berechne die Gesamtsumme der Noten für Schüler mit Noten 10 oder darüber, indem du map, filter und reduce zusammensetzt:

```js
const students = [
  { name: "Nick", grade: 10 },
  { name: "John", grade: 15 },
  { name: "Julia", grade: 19 },
  { name: "Nathalie", grade: 9 },
];

const aboveTenSum = students
  .map(student => student.grade) // wir mappen das students Array auf ein Array ihrer Noten
  .filter(grade => grade >= 10) // wir filtern das Noten-Array, um diejenigen 10 oder darüber zu behalten
  .reduce((prev, next) => prev + next, 0); // wir summieren alle Noten 10 oder darüber nacheinander

console.log(aboveTenSum) // 44 -- 10 (Nick) + 15 (John) + 19 (Julia), Nathalie unter 10 wird ignoriert
```

#### Erklärung

Betrachten wir das folgende Array von Zahlen für unsere Beispiele:

```js
const numbers = [0, 1, 2, 3, 4, 5, 6];
```

##### Array.prototype.map()

```js
const doubledNumbers = numbers.map(function(n) {
  return n * 2;
});
console.log(doubledNumbers); // [0, 2, 4, 6, 8, 10, 12]
```

Was passiert hier? Wir verwenden .map auf dem *numbers*-Array, die Map iteriert über jedes Element des Arrays und übergibt es unserer Funktion. Das Ziel der Funktion ist es, einen neuen Wert aus dem übergebenen Wert zu erzeugen und zurückzugeben, so dass map ihn ersetzen kann.

Lasst uns diese Funktion extrahieren, um es einmal klarer zu machen:

```js
const doubleN = function(n) { return n * 2; };
const doubledNumbers = numbers.map(doubleN);
console.log(doubledNumbers); // [0, 2, 4, 6, 8, 10, 12]
```

**Hinweis**: Du wirst diese Methode oft in Kombination mit [Pfeilfunktionen](#-pfeilfunktion) antreffen

```js
const doubledNumbers = numbers.map(n => n * 2);
console.log(doubledNumbers); // [0, 2, 4, 6, 8, 10, 12]
```

```numbers.map(doubleN)``` produziert ```[doubleN(0), doubleN(1), doubleN(2), doubleN(3), doubleN(4), doubleN(5), doubleN(6)]```, was gleich ```[0, 2, 4, 6, 8, 10, 12]``` ist.

> **Hinweis:** Wenn du kein neues Array zurückgeben musst und nur eine Schleife mit Nebeneffekten machen willst, solltest du vielleicht stattdessen eine for / forEach-Schleife anstelle von map verwenden.

##### Array.prototype.filter()

```js
const evenNumbers = numbers.filter(function(n) {
  return n % 2 === 0; // true, wenn "n" gerade ist, false, wenn "n" ungerade ist
});
console.log(evenNumbers); // [0, 2, 4, 6]
```

**Hinweis**: Du wirst diese Methode oft in Kombination mit [Pfeilfunktionen](#-pfeilfunktion) antreffen

```js
const evenNumbers = numbers.filter(n => n % 2 === 0);
console.log(evenNumbers); // [0, 2, 4, 6]
```

Wir verwenden .filter auf dem *numbers*-Array, filter iteriert über jedes Element des Arrays und übergibt es unserer Funktion. Das Ziel der Funktion ist es, einen Boolean zurückzugeben, der bestimmt, ob der aktuelle Wert behalten wird oder nicht. Filter gibt dann das Array nur mit den behaltenen Werten zurück.

##### Array.prototype.reduce()

Das Ziel der reduce-Methode ist es, alle Elemente des Arrays, über das sie iteriert, in einen einzigen Wert zu *reduzieren*. Wie diese Elemente aggregiert werden, liegt bei dir.

```js
const sum = numbers.reduce(
  function(acc, n) {
    return acc + n;
  },
  0 // Wert der Akkumulatorvariablen beim ersten Iterationsschritt
);

console.log(sum) // 21
```

**Hinweis**: Du wirst diese Methode oft in Kombination mit [Pfeilfunktionen](#-pfeilfunktion) antreffen

```js
const sum = numbers.reduce((acc, n) => acc + n, 0);
console.log(sum) // 21
```

Wie bei den .map- und .filter-Methoden wird .reduce auf einem Array angewandt und nimmt eine Funktion als ersten Parameter.

Diesmal gibt es allerdings Änderungen:

- .reduce nimmt zwei Parameter

Der erste Parameter ist eine Funktion, die bei jedem Iterationsschritt aufgerufen wird.

Der zweite Parameter ist der Wert der Akkumulatorvariablen (*acc* hier) beim ersten Iterationsschritt (lies den nächsten Punkt, um dies zu verstehen).

- Funktionsparameter

Die Funktion, die du als ersten Parameter von .reduce übergibst, nimmt zwei Parameter entgegen. Der erste (*acc* hier) ist die Akkumulatorvariable, während der zweite Parameter (*n*) das aktuelle Element ist.

Die Akkumulatorvariable entspricht dem Rückgabewert deiner Funktion im **vorherigen** Iterationsschritt. Beim ersten Schritt der Iteration ist *acc* gleich dem Wert, den du als zweiten Parameter von .reduce übergeben hast.

###### Beim ersten Iterationsschritt

```acc = 0```, weil wir 0 als zweiten Parameter für reduce übergeben haben

```n = 0```, erstes Element des *numbers*-Arrays

Die Funktion gibt *acc* + *n* --> 0 + 0 --> 0 zurück

###### Beim zweiten Iterationsschritt

```acc = 0```, weil es der Wert ist, den die Funktion im vorherigen Iterationsschritt zurückgegeben hat

```n = 1```, zweites Element des *numbers*-Arrays

Die Funktion gibt *acc* + *n* --> 0 + 1 --> 1 zurück

###### Beim dritten Iterationsschritt

```acc = 1```, weil es der Wert ist, den die Funktion im vorherigen Iterationsschritt zurückgegeben hat

```n = 2```, drittes Element des *numbers*-Arrays

Die Funktion gibt *acc* + *n* --> 1 + 2 --> 3 zurück

###### Beim vierten Iterationsschritt

```acc = 3```, weil es der Wert ist, den die Funktion im vorherigen Iterationsschritt zurückgegeben hat

```n = 3```, viertes Element des *numbers*-Arrays

Die Funktion gibt *acc* + *n* --> 3 + 3 --> 6 zurück

###### [...] Beim letzten Iterationsschritt

```acc = 15```, weil es der Wert ist, den die Funktion im vorherigen Iterationsschritt zurückgegeben hat

```n = 6```, letztes Element des *numbers*-Arrays

Die Funktion gibt *acc* + *n* --> 15 + 6 --> 21 zurück

Da dies der letzte Iterationsschritt ist, gibt **.reduce** 21 zurück.

##### Array.prototype.find()

```js
const greaterThanZero = numbers.find(function(n) {
  return n > 0; // gibt die Nummer zurück, die gerade größer als 0 ist
});
console.log(greaterThanZero); // 1
```

**Hinweis**: Du wirst diese Methode oft in Kombination mit [Pfeilfunktionen](#-pfeilfunktion) antreffen

Wir verwenden .find auf dem *numbers*-Array, .find iteriert über jedes Element des Arrays und übergibt es unserer Funktion, bis die Bedingung erfüllt ist. Das Ziel der Funktion ist es, das Element zurückzugeben, das die aktuelle Testfunktion erfüllt. Die .find-Methode führt die Callback-Funktion einmal für jeden Index des Arrays aus, bis der Callback einen wahren Wert zurückgibt.

**Hinweis**: Sie gibt sofort den Wert des Elements zurück (das die Bedingung erfüllt), wenn gefunden. Andernfalls gibt sie undefined zurück.

#### Externe Ressource

- [Verständnis von map / filter / reduce in JS](https://hackernoon.com/understanding-map-filter-and-reduce-in-javascript-5df1c7eee464)

### Spread-Operator "..."

Der Spread-Operator ```...``` wurde mit ES2015 eingeführt und wird verwendet, um Elemente eines iterierbaren Objekts (wie ein Array) an Stellen auszubreiten, an denen mehrere Elemente passen können.

#### Beispielcode

```js
const arr1 = ["a", "b", "c"];
const arr2 = [...arr1, "d", "e", "f"]; // ["a", "b", "c", "d", "e", "f"]
```

```js
function myFunc(x, y, ...params) {
  console.log(x);
  console.log(y);
  console.log(params)
}

myFunc("a", "b", "c", "d", "e", "f")
// "a"
// "b"
// ["c", "d", "e", "f"]
```

```js
const { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
console.log(x); // 1
console.log(y); // 2
console.log(z); // { a: 3, b: 4 }

const n = { x, y, ...z };
console.log(n); // { x: 1, y: 2, a: 3, b: 4 }
```

#### Erklärung

##### In Iterables (wie Arrays)

Wenn wir die folgenden zwei Arrays haben:

```js
const arr1 = ["a", "b", "c"];
const arr2 = [arr1, "d", "e", "f"]; // [["a", "b", "c"], "d", "e", "f"]
```

*arr2* das erste Element ist ein Array, weil *arr1* so, wie es ist, in *arr2* eingefügt wird. Aber was wir wollen, ist, dass *arr2* ein Array von Buchstaben ist. Um dies zu erreichen, können wir die Elemente von *arr1* in *arr2* *ausbreiten*.

Mit dem Spread-Operator

```js
const arr1 = ["a", "b", "c"];
const arr2 = [...arr1, "d", "e", "f"]; // ["a", "b", "c", "d", "e", "f"]
```

##### Funktionsrestparameter

In Funktionsparametern können wir den Rest-Operator verwenden, um Parameter in einem Array einzufügen, über das wir iterieren können. Es gibt bereits ein **arguments**-Objekt, das an jede Funktion gebunden ist und einem Array mit allen Parametern entspricht, die in die Funktion eingegeben wurden.

```js
function myFunc() {
  for (var i = 0; i < arguments.length; i++) {
    console.log(arguments[i]);
  }
}

myFunc("Nick", "Anderson", 10, 12, 6);
// "Nick"
// "Anderson"
// 10
// 12
// 6
```

Aber nehmen wir an, dass wir wollen, dass diese Funktion einen neuen Schüler mit seinen Noten und seinem Durchschnitt erstellt. Wäre es nicht praktischer, die ersten beiden Parameter in zwei separate Variablen zu extrahieren und dann alle Noten in einem Array zu haben, über das wir iterieren können?

Genau das ermöglicht der Rest-Operator!

```js
function createStudent(firstName, lastName, ...grades) {
  // firstName = "Nick"
  // lastName = "Anderson"
  // [10, 12, 6] -- "..." nimmt alle anderen übergebenen Parameter und erzeugt eine "grades"-Arrayvariable, die sie enthält

  const avgGrade = grades.reduce((acc, curr) => acc + curr, 0) / grades.length; // berechnet den Durchschnitt aus den Noten

  return {
    firstName: firstName,
    lastName: lastName,
    grades: grades,
    avgGrade: avgGrade
  }
}

const student = createStudent("Nick", "Anderson", 10, 12, 6);
console.log(student);
// {
//   firstName: "Nick",
//   lastName: "Anderson",
//   grades: [10, 12, 6],
//   avgGrade: 9,33
// }
```

> **Hinweis:** Die Funktion createStudent ist schlecht, weil wir nicht überprüfen, ob grades.length existiert oder verschieden von 0 ist. Aber so ist es einfacher zu lesen, deshalb habe ich diesen Fall nicht behandelt.

##### Objekteigenschaften ausbreiten

Für dieses Beispiel empfehle ich, die vorherigen Erklärungen zum Rest-Operator bei iterierbaren Objekten und Funktionsparametern zu lesen.

```js
const myObj = { x: 1, y: 2, a: 3, b: 4 };
const { x, y, ...z } = myObj; // Objektdestrukturierung hier
console.log(x); // 1
console.log(y); // 2
console.log(z); // { a: 3, b: 4 }

// z sind die restlichen Eigenschaften des destrukturierten Objekts: myObj-Objekt minus x- und y-Eigenschaften, die destrukturiert wurden

const n = { x, y, ...z };
console.log(n); // { x: 1, y: 2, a: 3, b: 4 }

// Hier werden die Eigenschaften von z-Objekten in n ausgespreitet
```

#### Externe Ressourcen

- [TC39 - Objekt rest/spread](https://github.com/tc39/proposal-object-rest-spread)
- [Einführung in den Spread-Operator - WesBos](https://github.com/wesbos/es6-articles/blob/master/28%20-%20Spread%20Operator%20Introduction.md)
- [JavaScript & der Spread-Operator](https://codeburst.io/javascript-the-spread-operator-a867a71668ca)
- [6 großartige Verwendungen des Spread-Operators](https://davidwalsh.name/spread-operator)

### Objekteigenschaften Kurzschreibweise

Wenn man einer Objekteigenschaft eine Variable zuweist, deren Name gleich dem Eigenschaftsnamen ist, kann man folgendes tun:

```js
const x = 10;
const myObj = { x };
console.log(myObj.x) // 10
```

#### Erklärung

Normalerweise (vor ES2015) wenn du ein neues *Objektliteral* deklarierst und Variablen als Werte für Objekteigenschaften verwenden möchtest, würdest du diesen Code schreiben:

```js
const x = 10;
const y = 20;

const myObj = {
  x: x, // weist x Variable Wert myObj.x zu
  y: y // weist y Variable Wert myObj.y zu
};

console.log(myObj.x) // 10
console.log(myObj.y) // 20
```

Wie du sehen kannst, ist das ziemlich wiederholend, weil die Namen der Eigenschaften von myObj den Variablennamen entsprechen, die du diesen zuweisen willst.

Mit ES2015 kannst du diese Abkürzung verwenden, wenn der Variablenname dem Namen der Eigenschaft entspricht:

```js
const x = 10;
const y = 20;

const myObj = {
  x,
  y
};

console.log(myObj.x) // 10
console.log(myObj.y) // 20
```

#### Externe Ressourcen

- [Property shorthand - ES6 Features](http://es6-features.org/#PropertyShorthand)


### Promises

Ein Promise ist ein Objekt, das synchron aus einer asynchronen Funktion zurückgegeben werden kann ([ref](https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-promise-27fc71e77261#3cd0)).

Promises können verwendet werden, um der [Callback-Hölle](http://callbackhell.com/) zu entkommen, und sie begegnen uns in modernen JavaScript-Projekten immer häufiger.

#### Beispielcode

```js
const fetchingPosts = new Promise((res, rej) => {
  $.get("/posts")
    .done(posts => res(posts))
    .fail(err => rej(err));
});

fetchingPosts
  .then(posts => console.log(posts))
  .catch(err => console.log(err));
```

#### Erklärung

Wenn du eine *Ajax-Anfrage* machst, ist die Antwort nicht synchron, weil du eine Ressource anforderst, die einige Zeit zur Antwort braucht. Sie könnte sogar nie kommen, falls die angeforderte Ressource aus irgendeinem Grund nicht verfügbar ist (404).

Um diese Art von Situation zu handhaben, hat uns ES2015 *Promises* gegeben. Promises können drei verschiedene Zustände haben:

- Pending (Im Warten)
- Fulfilled (Erfüllt)
- Rejected (Abgelehnt)

Nehmen wir an, wir möchten Promises verwenden, um eine Ajax-Anfrage zu tätigen und die Ressource X zu holen.

##### Das Promise erstellen

Zuerst erstellen wir ein Promise. Wir verwenden die jQuery get-Methode, um unsere Ajax-Anfrage an X zu stellen.

```js
const xFetcherPromise = new Promise( // Erstelle Promise mit dem "new" Schlüsselwort und speichere es in einer Variable
  function(resolve, reject) { // Der Promise-Konstruktor nimmt eine Funktion entgegen, die selbst die Parameter resolve und reject besitzt
    $.get("X") // Starte die Ajax-Anfrage
      .done(function(X) { // Sobald die Anfrage beendet ist...
        resolve(X); // ... erfülle das Promise mit dem Wert X als Parameter
      })
      .fail(function(error) { // Falls die Anfrage fehlschlägt...
        reject(error); // ... lehne das Promise mit dem Fehler als Parameter ab
      });
  }
)
```

Wie im obigen Beispiel zu sehen ist, nimmt das Promise-Objekt eine *Executor*-Funktion entgegen, die zwei Parameter **resolve** und **reject** hat. Diese Parameter sind Funktionen, die, wenn aufgerufen, den Promise-Zustand *pending* jeweils in einen *fulfilled* und *rejected* Zustand überführen.

Das Promise befindet sich in einem Pending-Zustand nach seiner Erstellung, und seine *Executor*-Funktion wird sofort ausgeführt. Sobald eine der Funktionen *resolve* oder *reject* in der *Executor*-Funktion aufgerufen wird, ruft das Promise seine zugehörigen Handler auf.

##### Verwendung von Promise-Handlern

Um das Ergebnis (oder den Fehler) des Promises zu erhalten, müssen wir ihm Handler zuweisen, indem wir Folgendes tun:

```js
xFetcherPromise
  .then(function(X) {
    console.log(X);
  })
  .catch(function(err) {
    console.log(err)
  })
```

Wenn das Promise erfolgreich ist, wird *resolve* ausgeführt und die Funktion, die als `.then` Parameter übergeben wurde, wird ausgeführt.

Wenn es fehlschlägt, wird *reject* ausgeführt und die Funktion, die als `.catch` Parameter übergeben wurde, wird ausgeführt.

> **Hinweis :** Wenn das Promise bereits erfüllt oder abgelehnt wurde, wenn ein entsprechender Handler angehängt wird, wird der Handler aufgerufen, sodass es keinen Wettlaufzustand zwischen dem Abschluss einer asynchronen Operation und dem Anhängen ihrer Handler gibt. [(Ref: MDN)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise#Description)

#### Externe Ressourcen

- [JavaScript Promises für Dummys - Jecelyn Yeen](https://scotch.io/tutorials/javascript-promises-for-dummies)
- [JavaScript Promise API - David Walsh](https://davidwalsh.name/promises)
- [Promises verwenden - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises)
- [Was ist ein Promise - Eric Elliott](https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-promise-27fc71e77261)
- [JavaScript Promises: Eine Einführung - Jake Archibald](https://developers.google.com/web/fundamentals/getting-started/primers/promises)
- [Promise Dokumentation - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)

### Template Literale

Template Literale sind eine [*Ausdrucksinterpolation*](https://en.wikipedia.org/wiki/String_interpolation) für ein- und mehrzeilige Strings.

Anders ausgedrückt, handelt es sich um eine neue String-Syntax, in der du bequem jede JavaScript-Ausdrücke verwenden kannst (beispielsweise Variablen).

#### Beispielcode

```js
const name = "Nick";
`Hallo ${name}, der folgende Ausdruck ist gleich vier : ${2+2}`;

// Hallo Nick, der folgende Ausdruck ist gleich vier: 4
```

#### Externe Ressourcen

- [String-Interpolation - ES6 Features](http://es6-features.org/#StringInterpolation)
- [ES6 Template Literale - Addy Osmani](https://developers.google.com/web/updates/2015/01/ES6-Template-Strings)

### Tagged Template Literale

Template Tags sind *Funktionen, die einem [Template Literal](#template-literals) vorangestellt werden können*. Wenn eine Funktion auf diese Weise aufgerufen wird, ist der erste Parameter ein Array der *Strings*, die zwischen den interpolierten Variablen des Templates auftreten, und die nachfolgenden Parameter sind die interpolierten Werte. Verwende einen Spread-Operator `...`, um alle zu erfassen. [(Ref: MDN)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_template_literals).

> **Hinweis :** Eine berühmte Bibliothek namens [styled-components](https://www.styled-components.com/) setzt schwer auf dieses Feature.

Hier ist ein Spielzeugbeispiel, wie sie funktionieren.
```js
function highlight(strings, ...values) {
  const interpolation = strings.reduce((prev, current) => {
    return prev + current + (values.length ? "<mark>" + values.shift() + "</mark>" : "");
  }, "");

  return interpolation;
}

const condiment = "Marmelade";
const meal = "Toast";

highlight`Ich mag ${condiment} auf ${meal}.`;
// "Ich mag <mark>Marmelade</mark> auf <mark>Toast</mark>."
```

Ein interessanteres Beispiel:
```js
function comma(strings, ...values) {
  return strings.reduce((prev, next) => {
    let value = values.shift() || [];
    value = value.join(", ");
    return prev + next + value;
  }, "");
}

const snacks = ['Äpfel', 'Bananen', 'Kirschen'];
comma`Ich mag ${snacks} zum Knabbern.`;
// "Ich mag Äpfel, Bananen, Kirschen zum Knabbern."
```

#### Externe Ressourcen
- [Wes Bos zu gekennzeichneten Template Literalen](http://wesbos.com/tagged-template-literals/)
- [Bibliothek von gängigen Template Tags](https://github.com/declandewet/common-tags)

### Imports / Exports

ES6-Module werden verwendet, um auf Variablen oder Funktionen in einem Modul zuzugreifen, die explizit von den Modulen exportiert wurden, die es importiert.

Ich empfehle dringend, sich die Ressourcen von MDN zu Import/Export anzusehen (siehe externe Ressourcen unten), da sie sowohl unkompliziert als auch vollständig sind.

#### Erklärung mit Beispielcode

##### Benannte Exports

Mit benannten Exports können mehrere Werte aus einem Modul exportiert werden.

> **Hinweis :** Du kannst nur [Erstklassige Bürger](https://en.wikipedia.org/wiki/First-class_citizen) mit einem Namen benannt exportieren.

```js
// mathConstants.js
export const pi = 3.14;
export const exp = 2.7;
export const alpha = 0.35;

// -------------

// myFile.js
import { pi, exp } from './mathConstants.js'; // Benannter Import -- Destructuring-ähnliche Syntax
console.log(pi) // 3.14
console.log(exp) // 2.7

// -------------

// mySecondFile.js
import * as constants from './mathConstants.js'; // Injiziere alle exportierten Werte in die Variable constants
console.log(constants.pi) // 3.14
console.log(constants.exp) // 2.7
```

Obwohl benannte Imports wie *Destructuring* aussehen, haben sie eine andere Syntax und sind nicht dasselbe. Sie unterstützen keine Standardwerte oder *tiefes* Destructuring.

Außerdem kannst du Aliase verwenden, aber die Syntax ist anders als die, die beim Destructuring verwendet wird:

```js
import { foo as bar } from 'myFile.js'; // foo wird importiert und in eine neue bar Variable injiziert
```

##### Standardimport / export

Bezüglich des Standardexports gibt es nur einen einzigen Standardexport pro Modul. Ein Standardexport kann eine Funktion, eine Klasse, ein Objekt oder irgendetwas anderes sein. Dieser Wert wird als der "Haupt"-exportierte Wert angesehen, da er am einfachsten zu importieren ist. [Ref: MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export#Description)

```js
// coolNumber.js
const ultimateNumber = 42;
export default ultimateNumber;

// ------------

// myFile.js
import number from './coolNumber.js';
// Standardexport, unabhängig von seinem Namen, wird automatisch in die Variable number injiziert;
console.log(number) // 42
```

Exportieren einer Funktion:

```js
// sum.js
export default function sum(x, y) {
  return x + y;
}
// -------------

// myFile.js
import sum from './sum.js';
const result = sum(1, 2);
console.log(result) // 3
```

#### Externe Ressourcen

- [ES6-Module in Stichpunkten](https://ponyfoo.com/articles/es6#modules)
- [Export - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export)
- [Import - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import)
- [Verständnis von ES6-Modulen](https://www.sitepoint.com/understanding-es6-modules/)
- [Destructuring Sonderfall - Importanweisungen](https://ponyfoo.com/articles/es6-destructuring-in-depth#special-case-import-statements)
- [Missverständnisse bezüglich ES6-Modulen - Kent C. Dodds](https://medium.com/@kentcdodds/misunderstanding-es6-modules-upgrading-babel-tears-and-a-solution-ad2d5ab93ce0)
- [Module in JavaScript](http://exploringjs.com/es6/ch_modules.html#sec_modules-in-javascript)

### <a name="this_def"></a> JavaScript *this*

Der *this*-Operator verhält sich anders als in anderen Sprachen und wird in den meisten Fällen durch die Art und Weise bestimmt, wie eine Funktion aufgerufen wird. ([Ref: MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this)).

Diese Vorstellung hat viele Feinheiten und ist ziemlich schwierig, daher schlage ich vor, in die unten aufgeführten externen Ressourcen einzutauchen. Ich werde das wiedergeben, was ich persönlich im Kopf habe, um zu bestimmen, was *this* gleich ist. Ich habe diesen Tipp aus [diesem Artikel von Yehuda Katz](http://yehudakatz.com/2011/08/11/understanding-javascript-function-invocation-and-this/) gelernt.

```js
function myFunc() {
  ...
}

// Nach jeder Anweisung findest du den Wert von *this* in myFunc

myFunc.call("myString", "hallo") // "myString" -- der erste .call-Parameterwert wird in *this* injiziert

// Im Nicht-Strict-Modus
myFunc("hallo") // window -- myFunc() ist syntaktischer Zucker für myFunc.call(window, "hallo")

// Im Strict-Modus
myFunc("hallo") // undefined -- myFunc() ist syntaktischer Zucker für myFunc.call(undefined, "hallo")
```

```js
var person = {
  myFunc: function() { ... }
}

person.myFunc.call(person, "test") // person Objekt -- der erste call-Parameter wird in *this* injiziert
person.myFunc("test") // person Objekt -- person.myFunc() ist syntaktischer Zucker für person.myFunc.call(person, "test")

var myBoundFunc = person.myFunc.bind("hallo") // Erstellt eine neue Funktion, in der wir "hallo" in den *this*-Wert injizieren
person.myFunc("test") // person Objekt -- Die bind-Methode hat keine Auswirkung auf die Originalmethode
myBoundFunc("test") // "hallo" -- myBoundFunc ist person.myFunc mit "hallo" gebunden an *this*
```

#### Externe Ressourcen

- [Verständnis von JavaScript-Funktionsaufrufen und "this" - Yehuda Katz](http://yehudakatz.com/2011/08/11/understanding-javascript-function-invocation-and-this/)
- [JavaScript this - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this)

### Klasse

JavaScript ist eine [prototypbasierte](https://en.wikipedia.org/wiki/Prototype-based_programming) Sprache (während Java beispielsweise eine [klassenbasierte](https://en.wikipedia.org/wiki/Class-based_programming) Sprache ist). ES6 hat JavaScript-Klassen eingeführt, die als syntaktischer Zucker für die prototypbasierte Vererbung gedacht sind und **kein** neues klassenbasiertes Vererbungsmodell darstellen ([ref](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes)).

Das Wort *class* ist tatsächlich irreführend, wenn du mit Klassen in anderen Sprachen vertraut bist. Wenn du es bist, vermeide Annahmen darüber, wie JavaScript-Klassen funktionieren, auf dieser Grundlage und betrachte es als eine völlig unterschiedliche Vorstellung.

Da dieses Dokument nicht den Anspruch hat, dir die Sprache von Grund auf beizubringen, gehe ich davon aus, dass du weißt, was Prototypen sind und wie sie sich verhalten. Wenn nicht, sieh dir die unten aufgeführten externen Ressourcen nach dem Beispielcode an.


#### Beispiele

Vor ES6, Prototyp-Syntax:

```js
var Person = function(name, age) {
  this.name = name;
  this.age = age;
}
Person.prototype.stringSentence = function() {
  return "Hallo, mein Name ist " + this.name + " und ich bin " + this.age;
}
```

Mit ES6-Klassensyntax:

```js
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  stringSentence() {
    return `Hallo, mein Name ist ${this.name} und ich bin ${this.age}`;
  }
}

const myPerson = new Person("Manu", 23);
console.log(myPerson.age) // 23
console.log(myPerson.stringSentence()) // "Hallo, mein Name ist Manu und ich bin 23
```

#### Externe Ressourcen

Zum Verständnis von Prototypen:

- [Understanding Prototypes in JS - Yehuda Katz](http://yehudakatz.com/2011/08/12/understanding-prototypes-in-javascript/)
- [A plain English guide to JS prototypes - Sebastian Porto](http://sporto.github.io/blog/2013/02/22/a-plain-english-guide-to-javascript-prototypes/)
- [Vererbung und die Prototyp-Kette - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain)

Zum Verständnis von Klassen:

- [ES6 Klassen im Detail - Nicolas Bevacqua](https://ponyfoo.com/articles/es6-classes-in-depth)
- [ES6-Features - Klassen](http://es6-features.org/#ClassDefinition)
- [JavaScript Klassen - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes)

### `Extends` und `super`

Das Schlüsselwort `extends` wird in Klassendeklarationen oder Klassenausdrücken verwendet, um eine Klasse zu erstellen, die ein Kind einer anderen Klasse ist ([Ref: MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends)). Die Unterklasse erbt alle Eigenschaften der Oberklasse und kann zusätzlich neue Eigenschaften hinzufügen oder die geerbten modifizieren.

Das Schlüsselwort `super` wird verwendet, um Funktionen eines Oberobjekts aufzurufen, einschließlich seines Konstruktors.

- Das Schlüsselwort `super` muss verwendet werden, bevor das Schlüsselwort `this` im Konstruktor verwendet wird.
- Der Aufruf von `super()` ruft den Konstruktor der Oberklasse auf. Wenn du einige Argumente im Konstruktor einer Klasse an den Konstruktor ihres Elternteils weitergeben möchtest, rufst du ihn mit `super(arguments)` auf.
- Wenn die Oberklasse eine Methode (auch statisch) namens `X` hat, kannst du mit `super.X()` diese in einer Unterklasse aufrufen.

#### Beispielcode

```js
class Polygon {
  constructor(height, width) {
    this.name = 'Polygon';
    this.height = height;
    this.width = width;
  }

  getHelloPhrase() {
    return `Hallo, ich bin ein ${this.name}`;
  }
}

class Square extends Polygon {
  constructor(length) {
    // Hier wird der Konstruktor der Oberklasse mit den Längen
    // für die Breite und Höhe des Polygons aufgerufen
    super(length, length);
    // Hinweis: In abgeleiteten Klassen muss super() aufgerufen werden, bevor du
    // 'this' verwenden kannst. Wenn du dies auslässt, wird ein Referenzfehler verursacht.
    this.name = 'Quadrat';
    this.length = length;
  }

  getCustomHelloPhrase() {
    const polygonPhrase = super.getHelloPhrase(); // Zugriff auf die Elternmethode mit super.X()-Syntax
    return `${polygonPhrase} mit einer Länge von ${this.length}`;
  }

  get area() {
    return this.height * this.width;
  }
}

const mySquare = new Square(10);
console.log(mySquare.area) // 100
console.log(mySquare.getHelloPhrase()) // 'Hallo, ich bin ein Quadrat' -- Square erbt von Polygon und hat Zugriff auf seine Methoden
console.log(mySquare.getCustomHelloPhrase()) // 'Hallo, ich bin ein Quadrat mit einer Länge von 10'
```

**Hinweis :** Wenn wir versucht hätten, `this` vor dem Aufruf von `super()` in der Square-Klasse zu verwenden, wäre ein ReferenceError ausgelöst worden:

```js
class Square extends Polygon {
  constructor(length) {
    this.height; // ReferenceError, super muss zuerst aufgerufen werden!

    // Hier wird der Konstruktor der Oberklasse mit den Längen
    // für die Breite und Höhe des Polygons aufgerufen
    super(length, length);

    // Hinweis: In abgeleiteten Klassen muss super() aufgerufen werden bevor du
    // 'this' verwenden kannst. Wenn du dies auslässt, wird ein Referenzfehler verursacht.
    this.name = 'Quadrat';
  }
}
```

#### Externe Ressourcen

- [Extends - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends)
- [Super-Operator - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super)
- [Vererbung - MDN](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance)

### Async Await

Zusätzlich zu [Promises](#promises) gibt es eine neue Syntax, die du vielleicht antriffst, um asynchronen Code zu handhaben, nämlich *async / await*.

Der Zweck von async/await-Funktionen ist es, die Verwendung von Promises synchron zu vereinfachen und ein Verhalten für eine Gruppe von Promises durchzuführen. Genau wie Promises ähnlich wie strukturierte Callbacks sind, ist async/await ähnlich wie die Kombination von Generatoren und Promises. Async-Funktionen geben *immer* ein Promise zurück. ([Ref: MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function))

> **Hinweis :** Du musst verstehen, was Promises sind und wie sie funktionieren, bevor du versuchst, async / await zu verstehen, da diese darauf basieren.

> **Hinweis 2:** [*await* muss in einer *async* Funktion verwendet werden](https://hackernoon.com/6-reasons-why-javascripts-async-await-blows-promises-away-tutorial-c7ec10518dd9#f3f0), was bedeutet, dass du await nicht auf der obersten Ebene unseres Codes verwenden kannst, da dies nicht innerhalb einer async-Funktion ist.

#### Beispielcode

```js
async function getGithubUser(username) { // das async-Schlüsselwort ermöglicht die Verwendung von await in der Funktion und bedeutet, dass die Funktion ein Promise zurückgibt
  const response = await fetch(`https://api.github.com/users/${username}`); // Die Ausführung wird hier pausiert, bis das von fetch zurückgegebene Promise aufgelöst ist
  return response.json();
}

getGithubUser('mbeaudru')
  .then(user => console.log(user)) // das Nutzer-Response loggen - await-Syntax kann nicht verwendet werden, da dieser Code nicht in einer async-Funktion ist
  .catch(err => console.log(err)); // wenn ein Fehler in unserer async-Funktion geworfen wird, werden wir ihn hier erwischen
```

#### Erklärung mit Beispielcode

*Async / Await* basiert auf Promises, ermöglicht aber eine imperativere Code-Stil.

Der *async*-Operator markiert eine Funktion als asynchron und wird immer ein *Promise* zurückgeben. Du kannst den *await*-Operator in einer *async*-Funktion verwenden, um die Ausführung in dieser Zeile zu pausieren, bis das vom Ausdruck zurückgegebene Promise entweder aufgelöst oder abgelehnt wird.

```js
async function myFunc() {
  // wir können den await-Operator verwenden, weil diese Funktion async ist
  return "hallo welt";
}

myFunc().then(msg => console.log(msg)) // "hallo welt" -- der Rückgabewert von myFunc wird durch den async-Operator in ein Promise umgewandelt
```

Wenn das *return*-Statement einer async-Funktion erreicht wird, wird das Promise mit dem zurückgegebenen Wert erfüllt. Wenn innerhalb einer async-Funktion ein Fehler geworfen wird, wechselt der Promise-Zustand zu *abgelehnt*. Wenn aus einer async-Funktion kein Wert zurückgegeben wird, wird trotzdem ein Promise zurückgegeben und löst ohne Wert auf, wenn die Ausführung der async-Funktion abgeschlossen ist.

Der *await*-Operator wird verwendet, um auf die Erfüllung eines *Promise* zu warten und kann nur im Körper einer *async*-Funktion verwendet werden. Beim Auftreffen wird die Codeausführung pausiert, bis das Promise erfüllt ist.

> **Hinweis :** *fetch* ist eine Funktion, die ein Promise zurückgibt, das einen AJAX-Anfrage ermöglicht

Sehen wir uns an, wie wir einen Github-Nutzer mit Promises zuerst abrufen würden:

```js
function getGithubUser(username) {
  return fetch(`https://api.github.com/users/${username}`).then(response => response.json());
}

getGithubUser('mbeaudru')
  .then(user => console.log(user))
  .catch(err => console.log(err));
```

Hier ist das äquivalente *async / await*:

```js
async function getGithubUser(username) { // promise + await-Schlüsselwortverwendung erlaubt
  die Antwort = await fetch(`https://api.github.com/users/${username}`); // Die Ausführung stoppt hier, bis das fetch-Promise erfüllt ist
  return response.json();
}

getGithubUser('mbeaudru')
  .then(user => console.log(user))
  .catch(err => console.log(err));
```

Die *async / await*-Syntax ist besonders praktisch, wenn du Promises verketten musst, die voneinander abhängig sind.

Wenn du beispielsweise einen Token abrufen musst, um einen Blogeintrag in einer Datenbank und dann die Autoreninformationen abzurufen:

> **Hinweis :** *await*-Ausdrücke müssen in Klammern eingefasst werden, um Methoden und Eigenschaften des aufgelösten Werts auf derselben Zeile aufzurufen.

```js
async function fetchPostById(postId) {
  const token = (await fetch('token_url')).json().token;
  const post = (await fetch(`/posts/${postId}?token=${token}`)).json();
  der Autor = (await fetch(`/users/${post.authorId}`)).json();

  post.author = author;
  return post;
}

fetchPostById('gzIrzeo64')
  .then(post => console.log(post))
  .catch(err => console.log(err));
```

##### Fehlerbehandlung

Sofern wir *try / catch*-Blöcke nicht um *await*-Ausdrücke herum hinzufügen, werden unerfasste Ausnahmen – unabhängig davon, ob sie im Körper Ihrer *async*-Funktion oder während ihrer Unterbrechung während *await* geworfen wurden – das Promise, das von der *async*-Funktion zurückgegeben wird, ablehnen. Die Verwendung des `throw`-Statements in einer asynchronen Funktion ist dasselbe wie die Rückgabe eines Promises, das abgelehnt wird. [(Ref: PonyFoo)](https://ponyfoo.com/articles/understanding-javascript-async-await#error-handling).

> **Hinweis :** Promises verhalten sich gleich!

Mit Promises sieht die Fehlerbearbeitungskette so aus:

```js
function getUser() { // Dieses Promise wird abgelehnt!
  return new Promise((res, rej) => rej("Benutzer nicht gefunden!"));
}

function getAvatarByUsername(userId) {
  return getUser(userId).then(user => user.avatar);
}

function getUserAvatar(username) {
  return getAvatarByUsername(username).then(avatar => ({ username, avatar }));
}

getUserAvatar('mbeaudru')
  .then(res => console.log(res))
  .catch(err => console.log(err)); // "Benutzer nicht gefunden!"
```

Das Äquivalent mit *async / await*:

```js
async function getUser() { // Das zurückgegebene Promise wird abgelehnt sein!
  wirf "Benutzer nicht gefunden!";
}

async function getAvatarByUsername(userId) => {
  const user = await getUser(userId);
  return user.avatar;
}

async function getUserAvatar(username) {
  var avatar = await getAvatarByUsername(username);
  return { username, avatar };
}

getUserAvatar('mbeaudru')
  .then(res => console.log(res))
  .catch(err => console.log(err)); // "Benutzer nicht gefunden!"
```

#### Externe Ressourcen

- [Async/Await - JavaScript.Info](https://javascript.info/async-await)
- [ES7 Async/Await](http://rossboucher.com/await/#/)
- [6 Gründe, warum JavaScripts Async/Await Promises wegblasen](https://hackernoon.com/6-reasons-why-javascripts-async-await-blows-promises-away-tutorial-c7ec10518dd9)
- [JavaScript awaits](https://dev.to/kayis/javascript-awaits)
- [Verwendung von Async Await in Express mit Node 8](https://medium.com/@Abazhenov/using-async-await-in-express-with-node-8-b8af872c0016)
- [Async-Funktion](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function)
- [Await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await)
- [Verwendung von async / await in express mit node 8](https://medium.com/@Abazhenov/using-async-await-in-express-with-node-8-b8af872c0016)


### Truthy / Falsy

In JavaScript ist ein Truthy- oder Falsy-Wert ein Wert, der in einen Boolean umgewandelt wird, wenn er in einem booleschen Kontext ausgewertet wird. Ein Beispiel für einen booleschen Kontext wäre die Auswertung einer ```if```-Bedingung:

Jeder Wert wird zu ```true``` umgewandelt, es sei denn, sie sind gleich:

- ```false```
- ```0```
- ```""``` (leerer String)
- ```null```
- ```undefined```
- ```NaN```

Hier sind Beispiele für *booleschen Kontext*:

- Auswertung einer ```if```-Bedingung

```js
if (myVar) {}
```

```myVar``` kann ein [first-class citizen](https://en.wikipedia.org/wiki/First-class_citizen) (Variable, Funktion, Boolean) sein, aber es wird in einen Boolean umgewandelt, weil es in einem booleschen Kontext ausgewertet wird.

- Nach dem logischen **NICHT** ```!```-Operator

Dieser Operator gibt false zurück, wenn sein einzelner Operand in true umgewandelt werden kann; andernfalls gibt er true zurück.

```js
!0 // true -- 0 ist falsy, also gibt es true zurück
!!0 // false -- 0 ist falsy, also gibt !0 true zurück, daher liefert !(!0) false
!!"" // false -- leerer String ist falsy, also NICHT (NICHT false) ist gleich false
```

- Mit dem *Boolean*-Objektkonstruktor

```js
new Boolean(0) // false
new Boolean(1) // true
```

- In einer ternären Auswertung

```js
myVar ? "truthy" : "falsy"
```

myVar wird in einem booleschen Kontext ausgewertet.

Sei vorsichtig beim Vergleichen von 2 Werten. Die Objektwerte (die zu true umgewandelt werden sollten) werden **nicht** in einen Boolean umgewandelt, sondern es wird gezwungen, in einen primitiven Wert mithilfe der [ToPrimitives-Spezifikation](http://javascript.info/object-toprimitive) umgewandelt. Intern, wenn ein Objekt mit einem Boolean-Wert wie `[] == true` verglichen wird, macht es `[].toString() == true`, also...

```js
let a = [] == true // a ist false, da [].toString() "" zurückgibt.
let b = [1] == true // b ist true, da [1].toString() "1" zurückgibt.
let c = [2] == true // c ist false, da [2].toString() "2" zurückgibt.
```

#### Externe Ressourcen

- [Truthy (MDN)](https://developer.mozilla.org/en-US/docs/Glossary/Truthy)
- [Falsy (MDN)](https://developer.mozilla.org/en-US/docs/Glossary/Falsy)
- [Truthy und Falsy-Werte in JS - Josh Clanton](http://adripofjavascript.com/blog/drips/truthy-and-falsy-values-in-javascript.html)

### Anamorphismen und Katamorphismen

#### Anamorphismen

Anamorphismen sind Funktionen, die von einem Objekt auf eine komplexere Struktur abbilden, die den Typ des Objekts enthält. Es ist der Prozess des *Entfaltens* einer einfachen Struktur in eine komplexere. Betrachte das Entfalten einer Ganzzahl in eine Liste von Ganzzahlen. Die Ganzzahl ist unser Ausgangsobjekt und die Liste von Ganzzahlen ist die komplexere Struktur.

**Beispielcode**

```js
function downToOne(n) {
  const list = [];

  for (let i = n; i > 0; --i) {
    list.push(i);
  }

  return list;
}

downToOne(5)
  //=> [ 5, 4, 3, 2, 1 ]
```

#### Katamorphismen

Katamorphismen sind das Gegenteil von Anamorphismen, da sie Objekte einer komplexeren Struktur nehmen und sie in einfachere Strukturen *falten*. Nehme das folgende Beispiel `product`, welches eine Liste von Ganzzahlen nimmt und eine einzelne Ganzzahl zurückgibt.

**Beispielcode**

```js
function product(list) {
  let product = 1;

  for (const n of list) {
    product = product * n;
  }

  return product;
}

product(downToOne(5)) // 120
```

#### Externe Ressourcen

* [Anamorphisms in JavaScript](http://raganwald.com/2016/11/30/anamorphisms-in-javascript.html)
* [Anamorphism](https://en.wikipedia.org/wiki/Anamorphism)
* [Catamorphism](https://en.wikipedia.org/wiki/Catamorphism)

### Generatoren

Eine andere Möglichkeit, die Funktion `downToOne` zu schreiben, ist die Verwendung eines Generators. Um ein `Generator`-Objekt zu instanziieren, muss man die `function *`-Deklaration verwenden. Generatoren sind Funktionen, die verlassen und später mit gespeichertem Kontext (Variablenbindungen) wieder betreten werden können.

Zum Beispiel kann die oben genannte Funktion `downToOne` wie folgt umgeschrieben werden:

```js
function * downToOne(n) {
  for (let i = n; i > 0; --i) {
    yield i;
  }
}

[...downToOne(5)] // [ 5, 4, 3, 2, 1 ]
```

Generatoren geben ein iterierbares Objekt zurück. Wenn die `next()`-Funktion des Iterators aufgerufen wird, wird sie ausgeführt, bis zum ersten `yield`-Ausdruck, welcher den zurückzugebenden Wert vom Iterator angibt oder mit `yield*`, das an eine andere Generatorfunktion delegiert. Wenn in dem Generator eine `return`-Anweisung aufgerufen wird, wird der Generator als beendet markiert und gibt den Rückgabewert zurück. Weitere Aufrufe von `next()` geben keine neuen Werte zurück.

**Beispielcode**

```js
// Yield-Beispiel
function * idMaker() {
  var index = 0;
  while (index < 2) {
    yield index;
    index = index + 1;
  }
}

var gen = idMaker();

gen.next().value; // 0
gen.next().value; // 1
gen.next().value; // undefined
```

Der `yield*`-Ausdruck ermöglicht einem Generator, eine andere Generatorfunktion während der Iteration aufzurufen.

```js
// Yield * Beispiel
function * genB(i) {
  yield i + 1;
  yield i + 2;
  yield i + 3;
}

function * genA(i) {
  yield i;
  yield* genB(i);
  yield i + 10;
}

var gen = genA(10);

gen.next().value; // 10
gen.next().value; // 11
gen.next().value; // 12
gen.next().value; // 13
gen.next().value; // 20
```

```js
// Generator Return-Beispiel
function* yieldAndReturn() {
  yield "Y";
  return "R";
  yield "unerreichbar";
}

var gen = yieldAndReturn()
gen.next(); // { value: "Y", done: false }
gen.next(); // { value: "R", done: true }
gen.next(); // { value: undefined, done: true }
```

#### Externe Ressourcen

* [Mozilla MDN Web Docs, Iteratoren und Generatoren](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators#Generators)

### Statische Methoden

#### Kurze Erklärung

Das Schlüsselwort `static` wird in Klassen verwendet, um statische Methoden zu deklarieren. Statische Methoden sind Funktionen in einer Klasse, die zum Klassenobjekt gehören und nicht für irgendeine Instanz dieser Klasse verfügbar sind.

#### Beispielcode

```js
class Repo {
  static getName() {
    return "Repo name is modern-js-cheatsheet"
  }
}

// Beachte, dass wir keine Instanz der Repo-Klasse erstellen mussten
console.log(Repo.getName()) // Der Name des Repos ist modern-js-cheatsheet

let r = new Repo();
console.log(r.getName()) // Ungefangener TypeError: r.getName ist keine Funktion
```

#### Ausführliche Erklärung

Statische Methoden können innerhalb einer anderen statischen Methode mithilfe des Schlüsselworts `this` aufgerufen werden, dies funktioniert jedoch nicht für nicht-statische Methoden. Nicht-statische Methoden können nicht direkt auf statische Methoden mit dem Schlüsselwort `this` zugreifen.

##### Andere statische Methoden aus einer statischen Methode aufrufen.

Um eine statische Methode aus einer anderen statischen Methode aufzurufen, kann das Schlüsselwort `this` verwendet werden wie folgt;

```js
class Repo {
  static getName() {
    return "Repo name is modern-js-cheatsheet"
  }

  static modifyName() {
    return this.getName() + '-added-this'
  }
}

console.log(Repo.modifyName()) // Der Name des Repos ist modern-js-cheatsheet-added-this
```

##### Statische Methoden aus nicht-statischen Methoden aufrufen.

Nicht-statische Methoden können auf zwei Weisen statische Methoden aufrufen;
1. ###### Mit dem Klassennamen.

Um Zugriff auf eine statische Methode von einer nicht-statischen Methode zu bekommen, verwenden wir den Klassennamen und rufen die statische Methode wie eine Eigenschaft auf. z.B `ClassName.StaticMethodName`

```js
class Repo {
  static getName() {
    return "Repo name is modern-js-cheatsheet"
  }

  useName() {
    return Repo.getName() + ' and it contains some really important stuff'
  }
}

// Wir müssen die Klasse instanziieren, um nicht-statische Methoden zu verwenden
let r = new Repo()
console.log(r.useName()) // Der Name des Repos ist modern-js-cheatsheet und enthält einige wirklich wichtige Dinge
```

2. ###### Mit dem Konstruktor

Statische Methoden können als Eigenschaften des Konstruktorobjekts aufgerufen werden.

```js
class Repo {
  static getName() {
    return "Repo name is modern-js-cheatsheet"
  }

  useName() {
    // Ruft die statische Methode als Eigenschaft des Konstruktors auf
    return this.constructor.getName() + ' and it contains some really important stuff'
  }
}

// Wir müssen die Klasse instanziieren, um nicht-statische Methoden zu verwenden
let r = new Repo()
console.log(r.useName()) // Der Name des Repos ist modern-js-cheatsheet und enthält einige wirklich wichtige Dinge
```

#### Externe Ressourcen
- [static keyword- MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static)
- [Statische Methoden- Javascript.info](https://javascript.info/class#static-methods)
- [Statische Mitglieder in ES6- OdeToCode](http://odetocode.com/blogs/scott/archive/2015/02/02/static-members-in-es6.aspx)

## Glossar

### <a name="scope_def"></a> Scope

Der Kontext, in dem Werte und Ausdrücke "sichtbar" sind oder referenziert werden können. Wenn eine Variable oder ein anderer Ausdruck "nicht im aktuellen Scope" ist, dann ist er nicht zur Verwendung verfügbar.

Quelle: [MDN](https://developer.mozilla.org/en-US/docs/Glossary/Scope)

### <a name="mutation_def"></a> Variablenmutation

Von einer Variablen wird gesagt, dass sie mutiert wurde, wenn ihr anfänglicher Wert sich danach geändert hat.

```js
var myArray = [];
myArray.push("firstEl") // myArray wird mutiert
```

Eine Variable wird als *unveränderlich* bezeichnet, wenn sie nicht mutiert werden kann.

[Schau dir den MDN Mutable-Artikel an](https://developer.mozilla.org/en-US/docs/Glossary/Mutable) für weitere Details.


================================================
FILE: translations/fa-IR.md
================================================
# برگه تقلب جاوااسکریپت مدرن

## مقدمه

### انگیزه

این سند، یک برگه تقلب برای مسائلی در جاوااسکپت است که به دفعات در کار با پروژه‌های مدرن و جدیدترین نمونه‌های کد با آن‌ها مواجه خواهید شد.

این راهنما قصد ندارد جاوااسکریپت را از بیخ آموزش بدهد بلکه می‌خواهد کمکی باشد برای دانش مقدماتی توسعه‌دهندگانی که ممکن است به واسطه مفاهیم جاوااسکریپت به کار برده شده در کدهای مدرن (مثلا در یادگیری ری‌اکت) با آن‌ها دست و پنجه نرم کنند.

در کنار این، تلاش می‌کنم گاهی نکاتی شخصی را ارائه دهم که ممکن است بحث برانگیز باشند اما هر کجا به آن‌ها اشاره کنم، بیان خواهم کرد که آن موارد، پیشنهادهای شخصی‌ام هستند.

> **نکته:** بیشتر مفاهمیمی که اینجا معرفی می‌شوند از به‌روزرسانی زبان جاوااسکریپت (ES2015 یا آن‌طور که معمولا گفته می‌شود ES6) می‌آیند. می‌توانید ویژگی‌های جدیدی که در این به‌روزرسانی اضافه شده‌اند را [این‌ جا](http://es6-features.org/) پیدا کنید که بسیار خوب ارائه شده‌اند.

## منابع مکمل

پیشنهاد می‌کنم وقتی در درک یک مفهوم دچار مشکل می‌شوید، در منابع زیر دنبال پاسخ بگردید:

- [MDN (Mozilla Developer Network)](https://developer.mozilla.org/en-US/search?q=)
- [You don't know JS (book)](https://github.com/getify/You-Dont-Know-JS)
- [Eloquent JavaScript (book)](https://eloquentjavascript.net)
- [Douglas Crockford's blog](https://www.crockford.com/javascript/)
- [ES6 Features with examples](http://es6-features.org)
- [Wes Bos blog (ES6)](http://wesbos.com/category/es6/)
- [Javascript Basics for Beginners](https://www.udacity.com/course/javascript-basics--ud804) - a free Udacity course
- [Reddit (JavaScript)](https://www.reddit.com/r/javascript/)
- [Google](https://www.google.com/) to find specific blog and resources
- [StackOverflow](https://stackoverflow.com/questions/tagged/javascript)

## فهرست مطالب

- [برگه تقلب جاوااسکریپت مدرن](#برگه-تقلب-جاوااسکریپت-مدرن)
  - [مقدمه](#مقدمه)
    - [انگیزه](#انگیزه)
    - [منابع مکمل](#منابع-مکمل)
  - [فهرست مطالب](#فهرست-مطالب)
  - [مفاهیم](#مفاهیم)
    - [اعلان متغیر: var، const، let](#اعلان-متغیر-var-const-let)
      - [توضیح کوتاه](#توضیح-کوتاه)
      - [نمونه کد](#نمونه-کد)
      - [توضیح مبسوط](#توضیح-مبسوط)
      - [منابع خارجی](#منابع-خارجی)
    - [تابع پیکانی](#تابع-پیکانی)
      - [نمونه کد](#نمونه-کد-1)
      - [توضیح مبسوط](#توضیح-مبسوط-1)
        - [اختصار](#اختصار)
        - [ارجاع this](#ارجاع-this)
      - [منابع مفید](#منابع-مفید)
    - [مقدار پیش‌فرض پارامتر تابع](#مقدار-پیشفرض-پارامتر-تابع)
      - [منابع خارجی](#منابع-خارجی-1)
    - [تجزیه اشیاء و آرایه‌ها](#تجزیه-اشیاء-و-آرایهها)
      - [توضیح با مثال](#توضیح-با-مثال)
      - [منابع مفید](#منابع-مفید-1)
    - [متدهای آرایه - map / filter / reduce / find](#متدهای-آرایه-map-filter-reduce-find)
      - [نمونه کد](#نمونه-کد-2)
      - [توضیح](#توضیح)
        - [متد ‪Array.prototype.map()‬](#متد-arrayprototypemap)
        - [متد ‪Array.prototype.filter()‬](#متد-arrayprototypefilter)
        - [متد ‪Array.prototype.reduce()‬](#متد-arrayprototypereduce)
        - [متد ‪Array.prototype.find()‬](#متد-arrayprototypefind)
      - [منبع خارجی](#منبع-خارجی)
    - [عملگر گسترش «...»](#عملگر-گسترش-)
      - [نمونه کد](#نمونه-کد-3)
      - [توضیح](#توضیح-1)
        - [در شمارش‌پذیرها (مانند آرایه)](#در-شمارشپذیرها-مانند-آرایه)
        - [پارامتر باقی (rest) تابع](#پارامتر-باقی-rest-تابع)
        - [گسترش خاصیت‌های شیء](#گسترش-خاصیتهای-شیء)
      - [منابع خارجی](#منابع-خارجی-2)
    - [میان‌بر خاصیت شیء](#میانبر-خاصیت-شیء)
      - [توضیح](#توضیح-2)
      - [منابع خارجی](#منابع-خارجی-3)
    - [وعده‌ها (Promises)](#وعدهها-promises)
      - [نمونه کد](#نمونه-کد-4)
      - [توضیح](#توضیح-3)
        - [ساخت یک وعده](#ساخت-یک-وعده)
        - [به‌کارگیری گرداننده وعده](#بهکارگیری-گرداننده-وعده)
      - [منابع خارجی](#منابع-خارجی-4)
    - [قالب لفظی (Template literals)](#قالب-لفظی-template-literals)
      - [نمونه کد](#نمونه-کد-5)
      - [منابع خارجی](#منابع-خارجی-5)
    - [قالب لفظی برچسب‌دار](#قالب-لفظی-برچسبدار)
      - [منابع خارجی](#منابع-خارجی-6)
    - [درون‌ریزی / برون‌ریزی](#درونریزی-برونریزی)
      - [توضیح به همراه نمونه کد](#توضیح-به-همراه-نمونه-کد)
        - [برون‌ریزی بانام](#برونریزی-بانام)
        - [درون‌ریزی / برون‌ریزی پیش‌فرض](#درونریزی-برونریزی-پیشفرض)
      - [منابع خارجی](#منابع-خارجی-7)
    - [مفهوم this در جاوااسکریپت](#مفهوم-this-در-جاوااسکریپت)
      - [منابع خارجی](#منابع-خارجی-8)
    - [کلاس](#کلاس)
      - [نمونه‌ها](#نمونهها)
      - [منابع خارجی](#منابع-خارجی-9)
    - [کلیدواژه‌های `Extends` و `super`](#کلیدواژههای-extends-و-super)
      - [نمونه کد](#نمونه-کد-6)
      - [منابع خارجی](#منابع-خارجی-10)
    - [استفاده از Async Await](#استفاده-از-async-await)
      - [نمونه کد](#نمونه-کد-7)
      - [توضیح با نمونه کد](#توضیح-با-نمونه-کد)
        - [مدیریت خطا](#مدیریت-خطا)
      - [منابع خارجی](#منابع-خارجی-11)
    - [درستی / غلطی](#درستی-غلطی)
      - [منابع خارجی](#منابع-خارجی-12)
    - [توابع Anamorphisms و Catamorphisms](#توابع-anamorphisms-و-catamorphisms)
      - [تابع Anamorphisms](#تابع-anamorphisms)
        - [نمونه کد](#نمونه-کد-8)
      - [تابع Catamorphisms](#تابع-catamorphisms)
        - [نمونه کد](#نمونه-کد-9)
      - [منابع خارجی](#منابع-خارجی-13)
    - [تولیدکننده‌ها](#تولیدکنندهها)
      - [نمونه کد](#نمونه-کد-10)
      - [منابع خارجی](#منابع-خارجی-14)
    - [متدهای ایستا](#متدهای-ایستا)
      - [توضیح کوتاه](#توضیح-کوتاه-1)
        - [نمونه کد](#نمونه-کد-11)
      - [توضیح مبسوط](#توضیح-مبسوط-2)
        - [فراخوانی متد ایستا توسط متد ایستای دیگر](#فراخوانی-متد-ایستا-توسط-متد-ایستای-دیگر)
        - [فراخوانی متدهای ایستا توسط متدهای غیرایستا](#فراخوانی-متدهای-ایستا-توسط-متدهای-غیرایستا)
      - [منابع خارجی](#منابع-خارجی-15)
  - [واژه‌نامه](#واژهنامه)
    - [قلمرو](#قلمرو)
    - [تغییر متغیر](#تغییر-متغیر)

## مفاهیم

### اعلان متغیر: var، const، let

در جاوااسکریپت سه کلیدواژه برای اعلان یک متغیر وجود دارند که هر یک دارای ویژگی‌های خاص خود هستند. این کلیدواژه‌ها عبارت‌اند از `var` و `let` و `const`.

#### توضیح کوتاه

متغیرهایی که با `const` اعلان می‌شوند را نمی‌توان دوباره مقداردهی کرد در حالی که اگر همان متغیر با `var` یا `let` تعریف می‌شد، امکان این کار فراهم می‌بود.

پیشنهاد می‌کنم همیشه متغیرهای خود را به طور پیش‌فرض با `const` تعریف کنید مگر این که بخواهید آن را بعدا تغییر داده یا مقداردهی کنید که در این حالت پیشنهادم استفاده از `let` است.

|     |قلمرو|قابل مقداردهی|قابل تغییر|محدوده مرگ زمانی|
| --- | --- | --- | --- | --- |
|const|بلوک|خیر|بله|بله|
|let|بلوک|بله|بله|بله|
|var|تابع|بله|بله|خیر|

#### نمونه کد
```javascript
const person = "Nick";
person = "John" // خطایی اعلام می‌شود که مقدار متغییر نمی‌تواند تغییر کند
```

```javascript
let person = "Nick";
person = "John";
console.log(person) // "John", بازمقداردهی مجاز است
```

#### توضیح مبسوط
[قلمرو](#قلمرو) یک متغیر تقریبا به این معناست که «این متغیر در کجای کد قابل دسترس است».

##### استفاده از var
متغیرهایی که با `var` اعلان می‌شوند *در قلمروی تابع* دردسترس‌اند به این معنا که وقتی متغیری در یک تابع تعریف شود، هر چیزی در آن تابع می‌توان به آن متغیر دسترسی داشه باشد. در کنار این، یک متغیر *در قلمروی تابع* که داخل یک تابع تعریف شده است نمی‌تواند خارج از آن تابع در دسترس باشد.

پیشنهاد می‌کنم تصور کنید که یک متغیر *در قلمروی X* مانند آن است که آن متغیر، یکی خصوصیت (property) X باشد.


```javascript
function myFunction() {
  var myVar = "Nick";
  console.log(myVar); // "Nick" - متغیر داخل تابع در دسترس است
}
console.log(myVar); // ReferenceError - متغیر خارج از تابع در دسترس نیست
```
و این مثال:

```javascript
function myFunction() {
  var myVar = "Nick";
  if (true) {
    var myVar = "John";
    console.log(myVar); // "John"
    // چون متغیر در قلروی تابع است، مقدارش با مقدار جدید جایگزین می‌شود.
  }
  console.log(myVar); // "John" - ببینید که دستورات داخل شرط چه طور روی مقدار این متغیر اثر می‌گذارد
}
console.log(myVar); // ReferenceError - متغیر خارج از تابع در دسترس نیست
```

افزون بر این، متغییرهایی که توسط `var` اعلان می‌شوند به بالای قلمرو در زمان اجرا منتقل می‌گردند.این چیزی است که آن را [var hoisting](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var#var_hoisting) می‌خوانیم.

این بخش از کد:

```js
console.log(myVar) // undefined -- no error raised
var myVar = 2;
```

در زمان اجرا به این شکل فهمیده می‌شود:

```js
var myVar;
console.log(myVar) // undefined -- no error raised
myVar = 2;
```

##### استفاده از let
شباهت‌هایی زیادی میان `let` و `var` وجود دارد اما متغیرهایی که با `let` تعریف می‌شوند:

- *در قلمروی بلوک* هستند
- پیش از مقداردهی قابل دسترسی **نیستند**
- نمی‌توانند در همان قلمرو بازاعلان شوند

بگذارید اثر تعریف متغیر در قلمروی بلوک را در همان مثال‌های پیشین ببینیم:

```javascript
function myFunction() {
  let myVar = "Nick";
  if (true) {
    let myVar = "John";
    console.log(myVar); // "John"
    // چون myVar یک متغیر در قلمروی بلوک است، در واقع یک متغیر جدید اعلان کرده‌ایم.
    // این متغیر خارج از این بلوک قابل دسترس نیست و در حقیقت، کاملا مستقل
    // از آن متغیر myVar است که اول تعریف شده بود.
  }
  console.log(myVar); // "Nick", ببینید که چه طور دستورات داخل شرط، تاثیری روی متغیر بیرون شرط ندارد
}
console.log(myVar); // ReferenceError - متغیر خارج از تابع قابل دسترس نیست
```

حال ببینیم که یعنی چه که متغیرهای `let` (و `const`) پیش از مقداردهی دسترسی نیستند:

```js
console.log(myVar) // ReferenceError !
let myVar = 2;
```

بر خلاف متغیرهای `var`، اگر تلاش کنید یک متغیر `let` یا `const` را پیش از مقداردهی بخوانید یا رویش بنویسید، خطا دریافت خواهید کرد. این پدیده معمولا با نام *محدوده مرگ زمانی* یا [*Temporal dead zone*](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#Temporal_Dead_Zone_and_errors_with_let) یا به اختصار *TDZ* خوانده می‌شود.

> **نکته:** از منظر فنی، اعلان‌های متغیر با `let` و `const` نیز بالاتر اجرا می‌شوند (hoist) اما مقداردهی‌شان نه. از همین رو که این گونه ساخته شده‌اند که تا پیش از مقداردهی، قابل استفاده نباشند این حس ایجاد می‌شود که گویی مورد hoist قرار نگرده‌اند در حالی که قرار گرفته‌اند. اگر می‌خواهید بیشتر بدانید، به [این توضیح بسیار مبسوط](http://jsrocks.org/2015/01/temporal-dead-zone-tdz-demystified) مراجعه کنید.

به علاوه، نمی‌توانید متغیرهای `let` را مجددا اعلان کنید:

```js
let myVar = 2;
let myVar = 3; // SyntaxError
```

##### استفاده از const

متغیرهای اعلان شده با `const` مشابه متغیرهای `let` رفتار می‌کنند با این تفاوت که قابل مقداردهی مجدد نیستند. به طور خلاصه، متغیرهای `const`:

- *در قلمروی بلوک* هستند
- پیش از مقداردهی قابل دسترسی نیستند
- نمی‌توانند در همان قلمرو بازاعلان شوند
- نمی‌توانند مقداردهی مجدد شوند

```js
const myVar = "Nick";
myVar = "John" // خطایی می‌بینید که مقداردهی مجدد ممکن نیست
```

```js
const myVar = "Nick";
const myVar = "John" // خطایی می‌بینید که اعلان مجدد ممکن نیست
```

اما یک نکته ظریف در این جا وجود دارد: متغیرهای `const` [تغییرناپذیر](#تغییر-متغیر) یا immutable نیستند! به معنای دقیق‌تر، آرایه‌ها و شیءهایی که با `const` اعلان شده‌اند **می‌توانند** تغییر کنند.

برای شی‌ءها:

```js
const person = {
  name: 'Nick'
};
person.name = 'John' // کار می‌کند چون این متغیر کاملا مقداردهی نشده، می‌تواند تغییر کند
console.log(person.name) // "John"
person = "Sandra" // خطا دریافت خواهید کرد چون قابل مقداردهی مجدد نیست
```

برای آرایه‌ها:

```js
const person = [];
person.push('John'); // کار می‌کند چون این متغیر کاملا مقداردهی نشده، می‌تواند تغییر کند
console.log(person[0]) // "John"
person = ["Nick"] // خطا دریافت خواهید کرد چون قابل مقداردهی مجدد نیست
```

#### منابع خارجی


- [How let and const are scoped in JavaScript - WesBos](http://wesbos.com/javascript-scoping/)
- [Temporal Dead Zone (TDZ) Demystified](http://jsrocks.org/2015/01/temporal-dead-zone-tdz-demystified)

### تابع پیکانی

در به‌روزرسانی ES6 جاوااسکریپت، *توابع پیکانی* یا Arrow Function معرفی شدند که روشی دیگری برای اعلان و استفاده از توابع هستند. برخی از فواید این نوع توابع عبارت‌اند از:

- مختصرتر هستند
- مقدار *this* از محیط برداشته می‌شود
- بازگشت تلویحی

#### نمونه کد

- اختصار و بازگشت تلویحی

```js
function double(x) { return x * 2; } // روش سنتی
console.log(double(2)) // 4
```

```js
const double = x => x * 2; // همان تابع به صورت تابع پیکانی با مقدار بازگشتی تلویحی
console.log(double(2)) // 4
```

- ارجاع *this*

در تابع پیکانی، *this* معادل مقدار *this* در بافتار اجرای محاط بر تابع است. اساسا با توابع پیکانی شما نیازی به ترفند `that = this` پیش از فراخوانی تابع دیگری داخل یک تابع ندارید.

```js
function myFunc() {
  this.myVar = 0;
  setTimeout(() => {
    this.myVar++;
    console.log(this.myVar) // 1
  }, 0);
}
```

#### توضیح مبسوط

##### اختصار

توابع پیکانی در قیاس با توابع سندی به روش‌های زیادی مختصرتر هستند. بگذارید همه حالت‌های ممکن را مرور کنیم:

- بازگشت تصریحی در مقابل تلویحی

**بازگشت تصریحی** تابعی است که در آن کلیدواژه *return* در بدنه تابع استفاده شده باشد.

```js
  function double(x) {
    return x * 2; // صریحا از کلیدواژه بازگشت استفاده شده است
  }
```

در روش سنتی نوشتن تابع، بازگشت همیشه صریح بوده است. اما با توابع پیکانی، می‌توانید *بازگشت تلویحی* داشه باشید که یعنی برای بازگرداندن یک مقدار، نیازی به استفاده از کلیدواژه *return* ندارید.

```js
  const double = (x) => {
    return x * 2; // بازگشت صریح
  }
```

از آن جایی که این تابع فقط چیزی را بر می‌گرداند (فاقد هر گونه دستورالعملی پیش از کلیدواژه *return* است) می‌توانیم از بازگشت تلویحی استفاده کنیم.

```js
  const double = (x) => x * 2;
```

برای این منظور کافی است که کلیدواژه **return** و **گیومه‌ها را برداریم**. به همین دلیل است که این روش، بازگشت *تلویجی* خوانده می‌شود. کلیدواژه *return* وجود ندارد اما این تابع در واقع مقدار `x * 2` را برمی‌گرداند.

> **توجه:** اگر تابع شما مقداری (با *اثر جانبی*) بر نمی‌گرداند، در حقیقت بازگشت تلویحی یا تصریحی انجام نمی‌دهد.

در کنار این، اگر شما بخواهید تلویحا یک *شیء* را برگردانید **لازم است که آن را در پرانتز قرار دهید** چون در غیر این صورت، با آکولادهای بلوک دچار تداخل می‌شود.

```js
const getPerson = () => ({ name: "Nick", age: 24 })
console.log(getPerson()) // { name: "Nick", age: 24 } -- شیء به صورت تلویحی با کمک تابع پیکانی بازگشت داده شده است
```

- تنها یک آرگومان

اگر تابع شما تنها یک پارامتر دریافت می‌کند می‌توانید پرانتز را از اطراف آن بردارید. اگر کد **double** بالایی را در نظر بگیریم:

```js
  const double = (x) => x * 2; // این تابع پیکانی تنها یک پارامتر دریافت می‌کند
```

پرانتزهای اطراف پارامتر می‌توانند برداشته شوند.

```js
  const double = x => x * 2; // این تابع پیکانی تنها یک پارامتر دریافت می‌کند
```

- بدون آرگومان

وقتی ورودی‌ای به تابع پیکانی وجود ندارد باید یک جفت پرانتز وارد کنید مگر نه خطای نحوی دریافت خواهید کرد.

```js 
  () => {
   // پرانتز درج شده و همه چیز درست کار می‌کند
    const x = 2;
    return x;
  }
```

```js
  => {
   // پرانتز درج نشده و کد اجرا نخواهد شد
    const x = 2;
    return x;
  }
```

##### ارجاع *this*

برای درک این ویژگی تازه معرفی شده همراه توابع پیکانی لازم است بدانید که **this** چگونه در جاوااسکریپت رفتار می‌کند.

در یک تابع پیکانی، *this* معادل *this* در بافتار اجرایی محاط بر تابع است. این یعنی که تابع پیکانی به جای ایجاد یک *this* جدید، آن را از محیطی که در آن احاطه شده می‌قاپد.

بدون تابع پیکانی اگر شما بخواهید از طریق *this* به یک متغیر در تابعی داخل یک تابع دسترسی پیدا کنید لازم است که از ترفند *that = this* یا *self = this* استفاده کنید.

به عنوان مثال، استفاده کردن از تابع setTimeout داخل تابع myFunc:

```js
function myFunc() {
  this.myVar = 0;
  var that = this; // that = this trick
  setTimeout(
    function() { // یک‫ this جدید در قلمروی این تابع ساخته می‌شود
      that.myVar++;
      console.log(that.myVar) // 1

      console.log(this.myVar) // undefined -- اعلان تابع را ببینید
    },
    0
  );
}
```

اما با تابع پیکانی، *this* از محیط پیرامونی‌اش گرفته می‌شود:

```js
function myFunc() {
  this.myVar = 0;
  setTimeout(
    () => {
    // اینجا this از محیط پیرامونی‌اش یعنی تابع myFunc گرفته می‌شود
      this.myVar++;
      console.log(this.myVar) // 1
    },
    0
  );
}
```

#### منابع مفید

- [Arrow functions introduction - WesBos](http://wesbos.com/arrow-functions/)
- [JavaScript arrow function - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)
- [Arrow function and lexical *this*](https://hackernoon.com/javascript-es6-arrow-functions-and-lexical-this-f2a3e2a5e8c4)


### مقدار پیش‌فرض پارامتر تابع

از به‌روزرسانی ES2015 جاوااسکریپت می‌توانید با نحو زیر، مقدار پیش‌فرض برای پارامترهای تابع تنظیم کنید:

```js
function myFunc(x = 10) {
  return x;
}
console.log(myFunc()) // 10
console.log(myFunc(5)) // 5

console.log(myFunc(undefined)) // 10
console.log(myFunc(null)) // null
```

پارامتر پیش‌فرض تنها در دو و فقط دو موقعیت اعمال می‌شود:

- پارامتری ارائه نشده باشد
- پارامتر *undefined* ارائه شده باشد

به بیان دیگر، اگر مقدار *null* را به پارامتر پیش‌فرض بدهید، این مقدار **اعمال نخواهد شد**.

> **نکته:** تخصیص مقدار پیش‌فرض می‌تواند با پارامترهای destructured هم استفاده شود (مفهوم بعدی را برای مثال ببینید)

#### منابع خارجی

- [Default parameter value - ES6 Features](http://es6-features.org/#DefaultParameterValues)
- [Default parameters - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters)

### تجزیه اشیاء و آرایه‌ها

*تجزیه* (destructuring) روشی آسان برای ساخت متغیرهای جدید از راه استخراج مقادیر از داده‌های ذخیره شده در اشیاء یا آرایه‌هاست.

به عنوان مثال، *تجزیه کردن* می‌تواند به منظور تجزیه پارامترهای تابع و یا *this.props* در پروژه‌های ری‌اکت مورد استفاده قرار گیرد.

#### توضیح با مثال

- شیء

بگذارید شیء زیر را برای تمام مثال‌ها در نظر بگیریم:

```js
const person = {
  firstName: "Nick",
  lastName: "Anderson",
  age: 35,
  sex: "M"
}
```

بدون تجزیه کردن:

```js
const first = person.firstName;
const age = person.age;
const city = person.city || "Paris";
```

با تجزیه کردن، تماما در یک خط:

```js
const { firstName: first, age, city = "Paris" } = person; // همین و بس

console.log(age) // 35 -- ‫متغیر جدید age ساخته شده و معادل است با person.age 
console.log(first) // "Nick" -- ‫متغیر جدید first ساخته شده و معادل است با person.firstName
console.log(firstName) // ReferenceError -- ‫در واقع person.firstName وجود دارد اما نام متغیر جدیدی که ساخته شده،first است
console.log(city) // "Paris" -- ‫متغیر جدیدی به نام city ساخته شده است اما چون person.city تغیرنشده است، مقدار موجود در city برابر است با مقدار پیش‌فرض ارائه شده یعنی Paris
```

**نکته:** آکولادهای استفاده شده در `const { age } = person` بعد از *const* نه برای اعلان شیء یا بلوک بلکه به عنوان نحو تجزیه نوشته شده است.

- پارامترهای تابع

*تجزیه کردن* معمولا برای تجزیه پارامترهای شیء در توابع استفاده می‌شود.

بدون تجزیه کردن

```js
function joinFirstLastName(person) {
  const firstName = person.firstName;
  const lastName = person.lastName;
  return firstName + '-' + lastName;
}

joinFirstLastName(person); // "Nick-Anderson"
```

با تجزیه کردن پارامتر *person* شیء، ما به یک تابع جمع و جورتر دست پیدا می‌کنیم:

```js
function joinFirstLastName({ firstName, lastName }) { // ‫ما متغیرهای firstName و lastName را با تجزیه پارامترهای شیء person به دست می‌آوریم
  return firstName + '-' + lastName;
}

joinFirstLastName(person); // "Nick-Anderson"
```

استفاده از تجزیه به خصوص در زمان استفاده از توابع پیکانی، شیرین‌تر هم می‌شود:

```js
const joinFirstLastName = ({ firstName, lastName }) => firstName + '-' + lastName;

joinFirstLastName(person); // "Nick-Anderson"
```


- آرایه

آرایه زیر را در نظر بگیریم:

```js
const myArray = ["a", "b", "c"];
```

بدون تجزیه کردن

```js
const x = myArray[0];
const y = myArray[1];
```

با تجزیه کردن

```js
const [x, y] = myArray; // همین و پس

console.log(x) // "a"
console.log(y) // "b"
```

#### منابع مفید

- [ES6 Features - Destructuring Assignment](http://es6-features.org/#ArrayMatching)
- [Destructuring Objects - WesBos](http://wesbos.com/destructuring-objects/)
- [ExploringJS - Destructuring](http://exploringjs.com/es6/ch_destructuring.html)

### متدهای آرایه - map / filter / reduce / find

خواستگاه متدهای *Map*، *filter*، *reduce* و *find* برای آرایه، یک پارادایم برنامه‌نویسی به نام برنامه‌نویسی تابعی یا [*functional programming*](https://medium.com/javascript-scene/master-the-javascript-interview-what-is-functional-programming-7f218c68b3a0) است.

به طور خلاصه:

- متد ‪**Array.prototype.map()** ‬ یک آرایه دریافت می‌کند، کاری روی تک تک اعضای آن انجام می‌دهد و آرایه‌ای حاوی اعضای تغییریافته باز می‌گرداند.
- متد ‪**Array.prototype.filter()** ‬ یک آرایه دریافت می‌کند، عضو به عضو پیش می‌رود و تصمیم می‌گیرد که آیا آن عضو در آرایه‌ای که بازگشت داده خواهد شد باقی بماند یا خیر. نهایتا هم یک آرایه از اعضای تایید شده را باز می‌گرداند.
- متد ‪**Array.prototype.reduce()** ‬ یک آرایه دریافت ی‌کند اعضای آن را روی هم ریخته و به صورت یک مقدار واحد باز می‌گرداند.
- متد ‪**Array.prototype.find()** ‬ یک آرایه دریافت می‌کند و اولین عضوی را که شرط اعلام شده را داشته باشد باز می‌گرداند.

پیشنهاد می‌کنم که تا می‌توانید از اصول برنامه‌نویسی تابعی بهره ببرید زیرا قابل ترکیب، موجز و زیبا هستند.

با این چهار متدی که اشاره شد، می‌توانید در موارد بسیاری از به کار بردن حلقه *for* و *forEach* اجتناب کنید. به جای حلقه *for* سعی کنید از ترکیب این چهار متد استفاده کنید. شاید در نگاه اول قدری چالش برانگیز باشد. طبیعی است چون لازم است روش جدیدی برای اندیشیدن را فرابگیرید. اما وقتی این مهارت را فرابگیرید، کارها آسان‌تر می‌شوند.

#### نمونه کد

```js
const numbers = [0, 1, 2, 3, 4, 5, 6];
const doubledNumbers = numbers.map(n => n * 2); // [0, 2, 4, 6, 8, 10, 12]
const evenNumbers = numbers.filter(n => n % 2 === 0); // [0, 2, 4, 6]
const sum = numbers.reduce((prev, next) => prev + next, 0); // 21
const greaterThanFour = numbers.find((n) => n>4); // 5
```
محاسبه مجموع نمرات دانش‌آموزانی که نمره ۱۰ یا بالاتر گرفته‌اند با کمک ترکیب متدهای map و filter و reduce:

```js
const students = [
  { name: "Nick", grade: 10 },
  { name: "John", grade: 15 },
  { name: "Julia", grade: 19 },
  { name: "Nathalie", grade: 9 },
];

const aboveTenSum = students
  .map(student => student.grade) // ‫ما آرایه student را روی آرایه‌ای از نمره‌های‌شان نگاشت (map) کردیم
  .filter(grade => grade >= 10) // ‫ما آرایه grades را به منظور نگه‌داشتن نمره‌های ۱۰ و بالاتر مورد پالایش (filter) قرار دادیم
  .reduce((prev, next) => prev + next, 0); // همه نمره‌های ۱۰ و بالاتر را یک به یک با هم جمع کردیم 

console.log(aboveTenSum) // 44 -- 10 (Nick) + 15 (John) + 19 (Julia), Nathalie below 10 is ignored
```

#### توضیح

بیایید آرایه اعداد زیر را به عنوان مثلا در نظر بگیریم:

```js
const numbers = [0, 1, 2, 3, 4, 5, 6];
```

##### متد ‪Array.prototype.map()

```js
const doubledNumbers = numbers.map(function(n) {
  return n * 2;
});
console.log(doubledNumbers); // [0, 2, 4, 6, 8, 10, 12]
```

چه شد؟ ما از متد ‪.map‬ روی آرایه *numbers* استفاده می‌کنیم. این متد می‌آید و روی یکایک اعضای آرایه حرکت می‌کند و مقدار آن‌ها را به تابع ما می‌دهد. هدف این تابع، تولید و بازگرداندن مقداری جدید بر اساس مقداری است که به آن داده شده و در نتیجه متد نگاشت (map)‌ می‌تواند مقدار جدید را جایگزین کند.

بگذارید فقط برای این مثال، این تابع را باز کرده و واضح‌ترش کنیم:

```js
const doubleN = function(n) { return n * 2; };
const doubledNumbers = numbers.map(doubleN);
console.log(doubledNumbers); // [0, 2, 4, 6, 8, 10, 12]
```

**نکته:** شما به دفعات خواهید دید که این متد در ترکیب با توابع پیکانی استفاده می‌شود.

```js
const doubledNumbers = numbers.map(n => n * 2);
console.log(doubledNumbers); // [0, 2, 4, 6, 8, 10, 12]
```

در این جا، ```numbers.map(doubleN)``` آرایهٔ ```[doubleN(0), doubleN(1), doubleN(2), doubleN(3), doubleN(4), doubleN(5), doubleN(6)]``` تولید می‌کند که معادل است با ```[0, 2, 4, 6, 8, 10, 12]```.

> **نکته:** اگر به جای بازگرداندن آرایه جدید فقط به دنبال ایجاد یک حلقهٔ دارای اثر جانبی هستید احتمالا باید به سراغ همان for یا forEach بروید نه map.

##### متد ‪Array.prototype.filter()

```js
const evenNumbers = numbers.filter(function(n) {
  return n % 2 === 0; // ‫اگر n زوج باشد مقدار true و در غیر این صورت false
});
console.log(evenNumbers); // [0, 2, 4, 6]
```

**نکته:** شما به دفعات خواهید دید که این متد در ترکیب با توابع پیکانی استفاده می‌شود.

```js
const evenNumbers = numbers.filter(n => n % 2 === 0);
console.log(evenNumbers); // [0, 2, 4, 6]
```

ما از متد ‪.filter‬ روی آرایه *numbers* استفاده می‌کنیم. این متد روی یکایک اعضای آرایه حرکت کرده و آن‌ها را به تابع ما می‌دهد. هدف تابع این است که یک مقدار بولی بازگرداند که مبنای تصمیم ما برای نگه داشتن آن عضو است. نهایتا filter آرایه‌ای از مقادیری را که نگه‌داشته است باز می‌گرداند.

##### متد ‪Array.prototype.reduce()

هدف متد کاهش (reduce) حرکت روی یکایک اعضای یک آرایه و کاستن آن‌ها به یک مقدار واحد است. این که چه طور این اعضا روی هم ریخته شوند به شما بستگی دارد.

```js
const sum = numbers.reduce(
  function(acc, n) {
    return acc + n;
  },
‪  0 // این، مقدار متغیر انباشت‌گر در نخستین گام محاسبه است
);

console.log(sum) // 21
```

**نکته:** شما به دفعات خواهید دید که این متد در ترکیب با توابع پیکانی استفاده می‌شود.

```js
const sum = numbers.reduce((acc, n) => acc + n, 0);
console.log(sum) // 21
```

درست هماهنند متدهای map و filter، متد reduce روی یک آرایه اعمال شده و یک تابع را به عنوان اولین پارامتر دریافت می‌کند.

این بار اما تفاوت‌هایی وجود دارد:

- متد ‪.reduce‬ دو پارامتر دریافت می‌کند

اولی پارامتر یک تابع است که در هر گام از حرکت روی اعضای آرایه فراخوانده می‌شود.

پارامتر دوم، مقدار متغیر انباشت‌گر (در این جا *acc*) در نخستین گام محاسبه است (برای فهمیدن، مورد بعدی را بخوانید).

- پارامترهای تابع

تابعی که به عنوان اولین پارامتر به ‪.reduce‬ می‌دهید دو پارامتر می‌خواهد. اولی (در این جا *acc*) متغیر انباشت‌گر و دومین پارامتر (*n*) عضو جاری آرایه است.

متغیر انباشت‌گر برابر است با مقدار بازگشت داده شده از تابع در گام **قبلی** محاسبه. در اولین گام از محاسبه، *acc* برابر است با مقداری که در دومین پارامتر ‪.reduce‬ وارد شده است.

###### در گام نخست

مقدار acc برابر صفر است زیرا در دومین پارامتر reduce مقدار صفر وارد شده است.

مقدار n هم صفر است چون اولین عضو آرایه *number* چنین مقداری دارد.

تابع، مقدار ‪*acc* + *n* --> 0 + 0 --> 0‬ را برمی‌گرداند.

###### در گام دوم

مقدار acc برابر صفر است چون تابع ما در مرحله قبل این مقدار را بازگردانده بود.

این بار n برابر یک است که دومین عضو آرایه *number* است.

این بار تابع مقدار ‪*acc* + *n* --> 0 + 1 --> 1‬ را بازمی‌گرداند.

###### در گام سوم

مقدار acc برابر یک است زیرا تابع ما در مرحله قبل این مقدار را بازگردانده بود.

این بار n برابر با ۲ است که سومین عضو آرایه *number* است.

تابع، مقدار ‪*acc* + *n* --> 1 + 2 --> 3‬ را باز می‌گرداند.


###### در چهارمین گام

مقدار acc برابر ۳ است زیرا تابع ما در مرحله قبل این مقدار را بازگردانده بود.

این بار n برابر با ۳ است که چهارمین عضو آرایه *number* است.

تابع، مقدار ‪*acc* + *n* --> 3 + 3 --> 6‬ را باز می‌گرداند.


###### نهایتا در آخرین گام

مقدار acc برابر ۱۵ است زیرا تابع ما در مرحله قبل این مقدار را بازگردانده بود.

مقدار n برابر با ۶ است که آخرین عضو آرایه *number* است.

تابع، مقدار ‪*acc* + *n* --> 15 + 6 --> 21‬ را باز می‌گرداند.

از آن جایی که این، آخرین گام محاسبه است، متد **‪.reduce‬** مقدار ۲۱ را باز می‌گرداند.

##### متد ‪Array.prototype.find()

```js
const greaterThanZero = numbers.find(function(n) {
  return n > 0; // return number just greater than 0 is present
});
console.log(greaterThanZero); // 1
```

**نکته:** شما به دفعات خواهید دید که این متد در ترکیب با توابع پیکانی استفاده می‌شود.

اینجا از متد یافتن یا find روی آرایه *numner* استفاده می‌کنیم. این متد روی یکایک اعضای آرایه حرکت کرده و تا زمانی که شرط تعیین شده برقرار شود آن‌ها را به تابع ما می‌دهد. هدف تابع، بازگرداندن عنصری است که روی آن، شرط موجود در تابع آزمون جاری محقق شود. متد find یک تابع callback را به ازای هر اندیس از آرایه و تا زمانی که آن تابع یک مقدار درست یا true را باز گرداند اجرا می‌کند.

**نکته:** این متد به محض پیدا کردن عضوی از آرایه که شرط مشخص شده را محقق می‌کند، مقدارش را باز می‌گرداند. در غیر این صورت مقدار undefined را باز خواهد گرداند.

#### منبع خارجی

- [Understanding map / filter / reduce in JS](https://hackernoon.com/understanding-map-filter-and-reduce-in-javascript-5df1c7eee464)

### عملگر گسترش «...»

عملگر گسترش `...` (spread) با ES2015 معرفی شد و برای گستردن عناصر یک متغیر قابل شمارش یا iterable (مانند یک آرایه) به مکان‌هایی است که چندین عنصر قابل جای‌گذاری هستند.

#### نمونه کد

```js
const arr1 = ["a", "b", "c"];
const arr2 = [...arr1, "d", "e", "f"]; // ["a", "b", "c", "d", "e", "f"]
```

```js
function myFunc(x, y, ...params) {
  console.log(x);
  console.log(y);
  console.log(params)
}

myFunc("a", "b", "c", "d", "e", "f")
// "a"
// "b"
// ["c", "d", "e", "f"]
```


```js
const { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
console.log(x); // 1
console.log(y); // 2
console.log(z); // { a: 3, b: 4 }

const n = { x, y, ...z };
console.log(n); // { x: 1, y: 2, a: 3, b: 4 }
```

#### توضیح

##### در شمارش‌پذیرها (مانند آرایه)

اگر دو آرایه زیر را داشته باشیم:

```js
const arr1 = ["a", "b", "c"];
const arr2 = [arr1, "d", "e", "f"]; // [["a", "b", "c"], "d", "e", "f"]
```

در آرایه *arr2*، اولین عضو ما یک آرایه است چرا که *arr1* همان‌گونه که هست در *arr2* تزریق شده است. اما چیزی که می‌خواهیم این است که *arr2*، آرایه‌ای از حروف باشد. برای این منظور می‌توانید عناصر *arr1* را در *arr2* *گسترش* دهیم.

با عملگر گسترش

```js
const arr1 = ["a", "b", "c"];
const arr2 = [...arr1, "d", "e", "f"]; // ["a", "b", "c", "d", "e", "f"]
```

##### پارامتر باقی (rest) تابع

در پارامترهای تابع می‌توانیم از عملگر باقی (rest) به منظور تزریق پارامترها به آرایه‌ای که رویش بتوانیم حلقه اجرا کنیم بهره می‌بریم. همواره یک شیء **arguments** همراه با هر تابعی وجود دارد که برابر است با آرایه‌ای از تمام پارامترهایی که به آن تابع حواله شده‌اند.

```js
function myFunc() {
  for (var i = 0; i < arguments.length; i++) {
    console.log(arguments[i]);
  }
}

myFunc("Nick", "Anderson", 10, 12, 6);
// "Nick"
// "Anderson"
// 10
// 12
// 6
```

اما حالتی را در نظر بگیرید که بخواهیم این تابع یک دانشجوی جدید همراه با معدل نمره‌هایش بسازد. آیا راحت‌تر نیست که که فقط دو پارامتر اول را استخراج کنیم و در دو متغیر مجزا قرار داده و سپس تمام نمره‌ها را آرایه‌ای بریزیم که بشود روی آن شمارش انجام داد؟

این دقیقا همان کاری است که عملگر باقی به ما اجازهٔ انجامش را می‌دهد!

```js
function createStudent(firstName, lastName, ...grades) {
  // firstName = "Nick"
  // lastName = "Anderson"
‪  // [10, 12, 6]
  // به کمک «...» تمام دیگر پارامترهای را دریافت و در آرایه «grades» ذخیره می‌کنیم

  const avgGrade = grades.reduce((acc, curr) => acc + curr, 0) / grades.length; //‫ معدل نمره‌های موجود در آرایه grades را محاسبه می‌کند

  return {
    firstName: firstName,
    lastName: lastName,
    grades: grades,
    avgGrade: avgGrade
  }
}

const student = createStudent("Nick", "Anderson", 10, 12, 6);
console.log(student);
// {
//   firstName: "Nick",
//   lastName: "Anderson",
//   grades: [10, 12, 6],
//   avgGrade: 9,33
// }
```

> **نکته:** تابع createStudent تابع بدی است زیرا بررسی نمی‌کنیم که اساسا grades.length وجود دارد یا خیر و یا متفاوت از صفر است یا نه. اما چون خوانایی آن به این شکل بهتر بود، آن را این گونه نوشتم.

##### گسترش خاصیت‌های شیء

برای این مورد پیشنهاد می‌کنم توضیحات قبلی را درباره عملگر باقی بر روی پارامترهای تابع و عناصر شمارش‌پذیر (iterables) بخوانید.

```js
const myObj = { x: 1, y: 2, a: 3, b: 4 };
const { x, y, ...z } = myObj; // تجزیه شیء
console.log(x); // 1
console.log(y); // 2
console.log(z); // { a: 3, b: 4 }

// متغیر z حاوی باقی مقادیر حاصل از تجزیهٔ شیء است: شیء myObj منهای مقادیر تجزیه شدهٔ x و y

const n = { x, y, ...z };
console.log(n); // { x: 1, y: 2, a: 3, b: 4 }

// اینجا z حاوی خاصیت‌های شیء است که در n گسترانده می‌شود.
```

#### منابع خارجی

- [TC39 - Object rest/spread](https://github.com/tc39/proposal-object-rest-spread)
- [Spread operator introduction - WesBos](https://github.com/wesbos/es6-articles/blob/master/28%20-%20Spread%20Operator%20Introduction.md)
- [JavaScript & the spread operator](https://codeburst.io/javascript-the-spread-operator-a867a71668ca)
- [6 Great uses of the spread operator](https://davidwalsh.name/spread-operator)

### میان‌بر خاصیت شیء

در زمان نسبت دادن یک متغیری به یک خاصیت شیء، اگر هر دو دارای نام یک‌سان باشند می‌توانیم این کار را انجام دهیم:

```js
const x = 10;
const myObj = { x };
console.log(myObj.x) // 10
```

#### توضیح

معمولا (پیش از ES2015) زمانی که یک *object literal* جدید تعریف می‌کنیم و بخواهیم متغیرها را به عنوان مقادیر خاصیت‌های شیء استفاده کنیم، باید چنین کدی بنویسیم:

```js
const x = 10;
const y = 20;

const myObj = {
  x: x, // ‫نسبت دادن مقدار متغیر x به myObj.x
  y: y // ‫نسبت دادن مقدار متغیر y به myObj.y
};

console.log(myObj.x) // 10
console.log(myObj.y) // 20
```
همان‌طور که می‌بینید، این کار خیلی تکراری است زیرا نام خاصیت‌های myObj دقیقا همان نام‌های متغیرهایی است که می‌خواهیم نسبت دهیم.

با معرفی ES2015، اگر نام متغیر همان نامی خاصیت باشد می‌توانیم از این روش میان‌بر استفاده کنیم:

```js
const x = 10;
const y = 20;

const myObj = {
  x,
  y
};

console.log(myObj.x) // 10
console.log(myObj.y) // 20
```

#### منابع خارجی

- [Property shorthand - ES6 Features](http://es6-features.org/#PropertyShorthand)

### وعده‌ها (Promises)

وعده یا promise یک شیء است که می‌تواند به صورت هم‌گام از یک تابع ناهم‌گام بازگردانده شود. ([ارجاع](https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-promise-27fc71e77261#3cd0)).

وعده‌ها می‌توانند برای پرهیز از دوزخ callback یا [callback hell](http://callbackhell.com/) استفاده شوند که در پروژه‌های مدرن جاوااسکریپت به کرات بروز می‌کنند.


#### نمونه کد

```js
const fetchingPosts = new Promise((res, rej) => {
  $.get("/posts")
    .done(posts => res(posts))
    .fail(err => rej(err));
});

fetchingPosts
  .then(posts => console.log(posts))
  .catch(err => console.log(err));
```

#### توضیح

وقتی که یک *درخواست ای‌جکس* می‌فرستید، پاسخ به‌هنگام یا هم‌گام نیست زیرا زمانی طول می‌کشد تا پاسخ این درخواست دریافت شود. حتی ممکن است به به دلیل دردسترس نبودن خدمت مورد نظر، این پاسخ هرگز به دست ما نرسد.

برای مدیریت چنین شرایطی، ES2015 *وعده‌ها* یا Promises را به ما هدیه داده است. وعده‌ها می‌توانند یکی از سه حالت وضعیت را داشته باشند:

- معلق (Pending)
- محقق شده (Fulfilled)
- رد شده (Rejected)

در نظر بگیرید که می‌خواهیم از وعده‌ها برای مدیریت یک درخواست ای‌جکس برای واکشی منبع X استفاده کنیم.

##### ساخت یک وعده

ابتدا یک وعده را می‌سازیم. از متد get جی‌کوئری برای فرستادن درخواست ای‌جکش به X استفاده خواهیم کرد.

```js
const xFetcherPromise = new Promise( // ‫با کلیدواژه new یک وعده می‌سازیم و آن را در یک متغیر ذخیره می‌کنیم
  function(resolve, reject) { //‫ سازنده وعده یک پارامتر تابع دریافت می‌کند که خودش دو پارامتر resolve و reject دارد
    $.get("X") // درخواست ای‌جکس را می‌فرستیم
      .done(function(X) { //‫ وقتی درخواست فرستاده شد...
        resolve(X); //‫ ...وعده با مقدار X به عنوان پارامتر رفع می‌شود
      })
      .fail(function(error) { //‫ اگر درخواست با شکست مواجه شود...
        reject(error); //‫ ...وعده با خطایی به عنوان پارامتر رد می‌شود
      });
  }
)
```

همان طور که در مثال بالا دیده می‌شود، شیء Promise یک تابع *اجراکننده* (executor) دریافت می‌کند که خودش دو پارامتر **resolve** و **reject** می‌گیرد. این پارامترها توابعی هستند که وقتی صدا زده شوند، متناسب با شرایطی که حادث می‌شود وضعیت وعده را به *محقق شده* یا *رد شده* تغییر می‌دهند.

وعده بعد از این جا ساخته می‌شود وارد وضعیت معلق می‌شود و تابع *اجرا کننده* بلادرنگ اجرا می‌شود. به محض صدا زده شدن *resolve* یا *reject* در تابع اجرا کننده، وعده اقدام به فراخوانی گرداننده (handler) مرتبط می‌کند.

##### به‌کارگیری گرداننده وعده

برای دریافت نتیجه (یا خطای) وعده بایستی به این شکل گرداننده‌ای به آن الصاق کنیم:

```js
xFetcherPromise
  .then(function(X) {
    console.log(X);
  })
  .catch(function(err) {
    console.log(err)
  })
```

اگر وعده با موفقیت انجام شود، *resolve* اجرا شده و تابعی به صورت پارامتر ‪`.then`‬ وارد شده است اجرا خواهد شد.

اگر به شکست بخورد، *reject* اجرا شده و تابعی که به صورت پارامتر به ‪`.catch`‬ وارد شده است اجرا خواهد شد.

> **نکته:** اگر وعده پیش از الصاق گرداننده، محقق یا رد شده باشد، گرداننده فراخوانده خواهد شد. مسابقه‌ای بین کامل شدن عملیات ناهم‌گام و الصاق شدن گرداننده‌های آن نیست. [ارجاع](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise#Description)

#### منابع خارجی

- [JavaScript Promises for dummies - Jecelyn Yeen](https://scotch.io/tutorials/javascript-promises-for-dummies)
- [JavaScript Promise API - David Walsh](https://davidwalsh.name/promises)
- [Using promises - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises)
- [What is a promise - Eric Elliott](https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-promise-27fc71e77261)
- [JavaScript Promises: an Introduction - Jake Archibald](https://developers.google.com/web/fundamentals/getting-started/primers/promises)
- [Promise documentation - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)

### قالب لفظی (Template literals)

قالب لفظی یک «درج عبارت» یا [*expression interpolation*](https://en.wikipedia.org/wiki/String_interpolation) برای رشته‌های تک یا چندخطی است.

به عبارت دیگر، یک نحو جدید رشته است که در آن می‌توانید به راحتی هر گونه عبارت (مثلا متغیرها) جاوااسکریپتی را استفاده کنید.

#### نمونه کد

```js
const name = "Nick";
`Hello ${name}, the following expression is equal to four : ${2+2}`;

// Hello Nick, the following expression is equal to four: 4
```

#### منابع خارجی

- [String interpolation - ES6 Features](http://es6-features.org/#StringInterpolation)
- [ES6 Template Strings - Addy Osmani](https://developers.google.com/web/updates/2015/01/ES6-Template-Strings)

### قالب لفظی برچسب‌دار

برچسب‌های قالب *توابعی هستند که می‌توانند به صورت پیش‌وند به [قالب‌های لفظی](#قالب-لفظی-template-literals) متصل شوند*. وقتی یک تابع به این روش صدا زده می‌شود اولین پارامتر، یک آرایه از *رشته‌ها* است که بین متغیرهای درج قالب ظاهرا می‌شوند و پارامتر بعدی مقادری است که باید درج شوند. از یک عملگر گسترش `...` برای دستیابی به همه آن‌ها بهره ببرید. [(مرجع)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_template_literals).

> **نکته:** کتابخانه معروفی به نام [styled-components](https://www.styled-components.com/) به شدت به این ویژگی متکی است.

این مثالی است از این که این قابلیت چگونه کار می‌کند:

```js
function highlight(strings, ...values) {
  const interpolation = strings.reduce((prev, current) => {
    return prev + current + (values.length ? "<mark>" + values.shift() + "</mark>" : "");
  }, "");

  return interpolation;
}

const condiment = "jam";
const meal = "toast";

highlight`I like ${condiment} on ${meal}.`;
// "I like <mark>jam</mark> on <mark>toast</mark>."
```

مثالی جالب‌تر:

```js
function comma(strings, ...values) {
  return strings.reduce((prev, next) => {
    let value = values.shift() || [];
    value = value.join(", ");
    return prev + next + value;
  }, "");
}

const snacks = ['apples', 'bananas', 'cherries'];
comma`I like ${snacks} to snack on.`;
// "I like apples, bananas, cherries to snack on."
```

#### منابع خارجی
- [Wes Bos on Tagged Template Literals](http://wesbos.com/tagged-template-literals/)
- [Library of common template tags](https://github.com/declandewet/common-tags)

### درون‌ریزی / برون‌ریزی

پیمانه‌ها (modules) در ES6 این امکان را فراهم می‌آورند که بتوان به متغیرها و توابعی که توسط یک پیمانه صریحا برون‌ریزی شده‌اند از پیمانه‌ای دیگر که آن پیمانه را درون‌ریزی می‌کنند دسترسی داشت.

قویا پیشنهاد می‌کنم به منابع موجود روی MDN درباره درون‌ریزی/برون‌ریزی یا import/export (به منابع خارجی این بخش رجوع کنید) نگاهی داشته باشید که هم سرراست است و هم کامل.

#### توضیح به همراه نمونه کد

##### برون‌ریزی بانام

برون‌ریزی بانام برای برون ریزی مقادیر از یک پیمانه مورد استفاده قرار می‌گیرد.

> **نکته:** فقط می‌توانید [first-class citizens](https://en.wikipedia.org/wiki/First-class_citizen) که دارای نام هستند را به صورت بانام برون‌ریزی کنید.

```js
// mathConstants.js
export const pi = 3.14;
export const exp = 2.7;
export const alpha = 0.35;

// -------------

// myFile.js
import { pi, exp } from './mathConstants.js'; // درون‌ریزی نام‌دار -- با نحوی مشابه تجزیه کردن
console.log(pi) // 3.14
console.log(exp) // 2.7

// -------------

// mySecondFile.js
import * as constants from './mathConstants.js';
// تزریق همه مقادیر برون‌ریزی شده به متغیر constants
console.log(constants.pi) // 3.14
console.log(constants.exp) // 2.7
```

در حالی که درون‌ریزی‌های نام‌دار شبیه به *تجزیه کردن* به نظر می‌رسند، اما دارای نحوی متفاوت بوده و مشابه آن نیستند. آن‌ها نه از مقادیر پیش‌فرض پشتیبانی مي‌کنند و نه از تجزیه کردن *عمیق*.

در کنار این، شما می‌توانید از مترادف‌ها (alias) استفاده کنید اما قواعد نحوی با آن چه که در تجزیه کردن وجود دارد متفاوت است.

```js
import { foo as bar } from 'myFile.js';
// در این جا foo درون‌ریزی شده و در متغیر جدیدی به نام bar تزریق شده است.
```

##### درون‌ریزی / برون‌ریزی پیش‌فرض

نظر به برون‌ریزی پیش‌فرض، هر پیمانه تنها می‌تواند یک برون‌ریزی پیش‌فرض داشته باشد. این برون‌ریزی پیش‌فرض می‌تواند یک تابع، یک کلاس، یک شیء و یا هر چیز دیگری باشد. این مقدار مقدار برون‌ریزی اصلی (main) شناخته می‌شود چرا که راحت‌ترین روش برای درون‌ریزی است. [مرجع: MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export#Description)

```js
// coolNumber.js
const ultimateNumber = 42;
export default ultimateNumber;

// ------------

// myFile.js
import number from './coolNumber.js';
// برون‌ریزی پیش‌فرض، مستقل از این که چه نامی داشته باشد به طور خودکار متغیر number درون‌ریزی شده است.
console.log(number) // 42
```

برون‌ریزی تابع

```js
// sum.js
export default function sum(x, y) {
  return x + y;
}
// -------------

// myFile.js
import sum from './sum.js';
const result = sum(1, 2);
console.log(result) // 3
```

#### منابع خارجی

- [ES6 Modules in bulletpoints](https://ponyfoo.com/articles/es6#modules)
- [Export - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export)
- [Import - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import)
- [Understanding ES6 Modules](https://www.sitepoint.com/understanding-es6-modules/)
- [Destructuring special case - import statements](https://ponyfoo.com/articles/es6-destructuring-in-depth#special-case-import-statements)
- [Misunderstanding ES6 Modules - Kent C. Dodds](https://medium.com/@kentcdodds/misunderstanding-es6-modules-upgrading-babel-tears-and-a-solution-ad2d5ab93ce0)
- [Modules in JavaScript](http://exploringjs.com/es6/ch_modules.html#sec_modules-in-javascript)

### مفهوم this در جاوااسکریپت

رفتار عملگر *this* جاوااسکریپت متفاوت است از دیگر زبان‌ها و در بسیاری موارد به این بستگی دارد که چه طور یک تابع فراخوانی شده باشد. ([مرجع: MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this))

این مفهوم ظرافت‌های بسیاری دارد و تا حدودی دشوار است. شدیدا پیشنهاد می‌کنم که شیرجه عمیقی بزنید به منابع خارجی‌ای که پایین‌تر معرفی شده‌اند. با این حال آن چه را که شخصا از چیستی *this* در ذهنم دارم را اینجا ارائه می‌کنم. این نکته را از [این مقاله به قلم یودا کتز](http://yehudakatz.com/2011/08/11/understanding-javascript-function-invocation-and-this/) فراگرفته‌ام.

```js
function myFunc() {
  ...
}
// پس از هر گزاره، مقدار *this* در تابع myFunc را خواهید دید

myFunc.call("myString", "hello") // "myString"
// مقدار اولین پارامتر ‪.call‬ در *this* تزریق می‌شود

// در حال غیرسخت‌گیرانه (non-strict mode)
myFunc("hello") // window
// در واقع ‪myFunc()‬ نحو راه‌دست‌تر برای myFunc.call(window,"hello") است

// در حالت سخت‌گیرانه (strict mode)
myFunc("hello") // undefined
اینجا ‪myFunc()‬ نحو راه‌دست‌تر برای myFunc.call(undefined, "hello") است
```

```js
var person = {
  myFunc: function() { ... }
}

person.myFunc.call(person, "test") // ‫شیء person
// اولین پارامتر call در *this* تزریق می‌شود
person.myFunc("test") // ‫شیء person
// اینجا ‪person.myFunc()‬ نحو راه‌دست‌تر برای person.myFunc.call(person, "test") است
var myBoundFunc = person.myFunc.bind("hello") // ‫تابعی جدید می‌سازد که ما «hello» را در *this* آن تزریق می‌کنیم.
person.myFunc("test") // ‫شیء person
// متد bind تاثیر روی متد اصلی ندارد
myBoundFunc("test") // "hello"
//تابع myBoundFunc در واقع همان person.myFunc است که در آن «hello» به *this* بند (bind) زده شده است.
```

#### منابع خارجی

- [Understanding JavaScript Function Invocation and "this" - Yehuda Katz](http://yehudakatz.com/2011/08/11/understanding-javascript-function-invocation-and-this/)
- [JavaScript this - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this)

### کلاس

جاوااسکریپت یک زبان برنامه‌نویسی بر پایه پیش‌نمونه یا [prototype-based](https://en.wikipedia.org/wiki/Prototype-based_programming) است (در حالی که جاوا یک زبان کلاس محور یا [class-based](https://en.wikipedia.org/wiki/Class-based_programming) است). ES6 کلاس‌های جاوااسکریپت را معرفی کرده است که بیشتر به منظور ارائه نحوی راه‌دست‌تر برای ارث‌بری مبتنی بر پیش‌نمونه است و نه یک مدل ارث‌بری کلاس‌محور ([مرجع](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes)).

اگر با کلاس‌ها در سایر زبان‌ها آشنایی داشته باشید، واژه *class* اینجا در واقع مستعد بروز خطاست. اگر آشنایی دارید، از تصور این که کلاس‌های جاوااسکریپت بر همان اساس کار می‌کنند پرهیز کنید و در نظر بگیرید که مفهومش در اینجا به کلی چیز دیگری است.

از آن جایی که این سند تلاش ندارد تا زبان را از بیخ آموزش بدهد، فرض خواهم کرد که شما با پیش‌نمونه‌ها (prototypes) و این که چه طور کار می‌کنند آشنایی دارید. اگر آشنایی ندارید به منابع خارجی همین بخش مراجعه کنید.

#### نمونه‌ها

نحو پیش‌نمونه‌ها پیش از ES6:

```js
var Person = function(name, age) {
  this.name = name;
  this.age = age;
}
Person.prototype.stringSentence = function() {
  return "Hello, my name is " + this.name + " and I'm " + this.age;
}
```

نحو کلاس پس از ES6:

```js
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  stringSentence() {
    return `Hello, my name is ${this.name} and I am ${this.age}`;
  }
}

const myPerson = new Person("Manu", 23);
console.log(myPerson.age) // 23
console.log(myPerson.stringSentence()) // "Hello, my name is Manu and I'm 23
```

#### منابع خارجی

برای فهم پیش‌نمونه:

- [Understanding Prototypes in JS - Yehuda Katz](http://yehudakatz.com/2011/08/12/understanding-prototypes-in-javascript/)
- [A plain English guide to JS prototypes - Sebastian Porto](http://sporto.github.io/blog/2013/02/22/a-plain-english-guide-to-javascript-prototypes/)
- [Inheritance and the prototype chain - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain)

برای فهم کلاس‌ها:

- [ES6 Classes in Depth - Nicolas Bevacqua](https://ponyfoo.com/articles/es6-classes-in-depth)
- [ES6 Features - Classes](http://es6-features.org/#ClassDefinition)
- [JavaScript Classes - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes)

### کلیدواژه‌های `Extends` و `super`

کلیدواژه `extends` در اعلان کلاس یا عبارات کلی برای ساخت یک کلاس که فرزند کلاس دیگری است استفاده می‌شود ([مرجع: MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends)). زیرکلاس تمام خاصیت‌های فراکلاس را به ارث می‌برد و افزون بر این می‌تواند خاصیت‌های جدید اضافه کند یا خاصیت‌های ارث برده را تغییر دهد.

کلیدواژه `super` برای فراخوانی توابع در والد شیء شامل سازنده (constructor) استفاده می‌شود.

- کلیدواژه `super` بایستی پیش از کلیدواژه `this` در constructor استفاده شود
- اجرای ‪`super()`‬، سازنده کلاس والد را فرامی‌خواند. برای فرستادن چند آرگومان از سازندهٔ کلاس به سازندهٔ کلاس والد از `super(arguments)` استفاده کنید.
- اگر کلاس والد متدی (حتی ایستا یا static) به نام `X` دارد می‌توانید از ‪`super.X()`‬ برای فراخوانی‌اش در کلاس فرزند استفاده کنید.

#### نمونه کد

```js
class Polygon {
  constructor(height, width) {
    this.name = 'Polygon';
    this.height = height;
    this.width = width;
  }

  getHelloPhrase() {
    return `Hi, I am a ${this.name}`;
  }
}

class Square extends Polygon {
  constructor(length) {
    // اینجا، سازندهٔ کلاس والد به همراه طول ارائه شده برای
    // عرض و ارتفاع چندضلعی فراخوانده می‌شود
    super(length, length);
    // نکته: در کلاس‌های مشتق شده، ‪super()‬ بایستی پیش از this فراخوانی
    // شود. در غیر این صورت خطای reference دریافت خواهید کرد.
    this.name = 'Square';
    this.length = length;
  }

  getCustomHelloPhrase() {
    const polygonPhrase = super.getHelloPhrase();
    // دسترسی به متد والد با نحو ‪super.X()
    return `${polygonPhrase} with a length of ${this.length}`;
  }

  get area() {
    return this.height * this.width;
  }
}

const mySquare = new Square(10);
console.log(mySquare.area) // 100
console.log(mySquare.getHelloPhrase()) // 'Hi, I am a Square'
// در واقع Square از Polygon ارث بده و به متدهای آن دسترسی دارد
console.log(mySquare.getCustomHelloPhrase()) // 'Hi, I am a Square with a length of 10'
```

**نکته:** اگر در کلاس Square پیش از فراخوانی `super()` از `this` استفاده کنید، خطای ReferenceError دریافت خواهید کرد.

```js
class Square extends Polygon {
  constructor(length) {
    this.height; // ReferenceError, super needs to be called first!

    // اینجا، سازندهٔ کلاس والد همراه با طول‌های ارائه شده
    // برای طول و عرض چندضلعی فراخوانی می‌شود.
    super(length, length);

    // توجه: در کلاس‌های مشتق شده، ‪super()‬ باید پیش از this
    // فراخوانی شود. در غیر این صورت خطا دریافت خواهید کرد.
    this.name = 'Square';
  }
}
```

#### منابع خارجی

- [Extends - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends)
- [Super operator - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super)
- [Inheritance - MDN](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance)

### استفاده از Async Await

افزون بر [وعده‌ها](#وعدهها-promises) ممکن است با یک نحو جدید دیگر نیز در مواجهه با کدهای ناهم‌گام مواجه شوید به نام *async / await*.

هدف توابع async/await، ساده‌سازی رفتار استفاده از وعده‌ها به صورت هم‌گام و انجام برخی رفتارها روی گروهی از وعده‌هاست. درست همان طور که وعده‌ها مشابه callbackهای ساختاردار هستند، async/await مشابه ترکیب سازنده‌ها (generators) و وعده‌هاست. ([مرجمع: MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function))

> **توجه:** لازم است پیش از تلاش برای فهم async / await بدانید که وعده‌ها چیستند و چگونه کار می‌کنند چرا که شالوده کار همان است.

> **نکته ۲:** [*await* بایستی با یک تابع *async* استفاده شود](https://hackernoon.com/6-reasons-why-javascripts-async-await-blows-promises-away-tutorial-c7ec10518dd9#f3f0) که یعنی نمی‌توانید از await در سطح بالای کدتان استفاده کنید چرا که داخل یک تابع ناهمگام یا async نیست.

#### نمونه کد

```js
async function getGithubUser(username) { 
// کلیدواژه asunc اجازه استفاده از await را در تابع می‌دهد که یعنی تابع، یک وعده را باز خواهد گرداند.
  const response = await fetch(`https://api.github.com/users/${username}`);
  // اجرای کد در اینجا متوقف می‌شود تا زمانی که وعده بازگردانده شده از fetch رفع شده و یک ‪responce.json()‬ بازگرداند
}

getGithubUser('mbeaudru')
  .then(user => console.log(user)) // logging user response
  // نمی‌توان از نحو await استفاده کرد چون این کد داخل یک تابع async نیست
  .catch(err => console.log(err)); // اگر خطایی در تابع ناهم‌گام ما بروز کند اینجا آن را دریافت خواهیم کرد
```

#### توضیح با نمونه کد

در واقع *Async / Await* برروی وعده‌ها ساخته شده اما اجازه می‌دهد به سبکی دستوری‌تر (imperative) کدنویسی کنیم.

عملگر *async* یک تابع را به عنوان تابع ناهم‌گام علامت‌گذاری می‌کند و همواره یک *وعده* یا Promise باز می‌گرداند. می‌توانید از عملگر *await* در یک تابع *async* به منظور ایجاد مکث در روند اجرا در آن خط تا زمانی که وعده بازگردانده شود استفاده شود. این وعده می‌تواند محقق یا رد شده باشد.

```js
async function myFunc() {
  // می‌توانیم از عملگر await استفاده کنیم زیرا در یک تابع async هستیم
  return "hello world";
}

myFunc().then(msg => console.log(msg)) // "hello world"
// به واسطه عملگر async، مقدار بازگشتی از myFunc به یک وعده تغییر یافته است
```

وقتی به دستور *return* در یک تابع ناهم‌گام یا async می‌رسیم، وعده با مقداری که بازگشت داده می‌شود محقق شده است. اگر خطایی داخل تابع async بروز کند، وضعیت وعده به *رد شده* تغییر می‌کند. اگر مقداری از تابع async بازگردانده نشود، با اتمام اجرای تابع async همچنان وعده‌ای باز گردانده می‌شود که فاقد مقدار است.

عملگر *await* برای آن استفاده می‌شود که منتظر محقق شدن *وعده* بمانیو و تنها می‌تواند در بدنه یک تابع *async* استفاده شود. به محض رسیدن اجرای برنامه به این خط، چرخه اجرا مکث می‌کند تا زمانی که وعده محقق شود.

> **توجه:** *fatch* تابعی است که وعده‌ای باز می‌گرداند و اجازه می‌دهد که یک درخواست ای‌جکس بفرستیم.

بگذارید ابتدا ببینیم چه طور می‌توانیم یک کاربر گیت‌هاب را با fetch دریافت کنیم:

```js
function getGithubUser(username) {
  return fetch(`https://api.github.com/users/${username}`).then(response => response.json());
}

getGithubUser('mbeaudru')
  .then(user => console.log(user))
  .catch(err => console.log(err));
```

و این، معادلش با استفاده از *async / await* است:

```js
async function getGithubUser(username) { // promise + await keyword usage allowed
  const response = await fetch(`https://api.github.com/users/${username}`); // اجرا در اینجا متوقف می‌شود تا وعده‫ fetch محقق شود
  Execution stops here until fetch promise is fulfilled
  return response.json();
}

getGithubUser('mbeaudru')
  .then(user => console.log(user))
  .catch(err => console.log(err));
```

نحو *async / await* به خصوص زمانی که می‌خواهید وعده‌های مستقل از هم را به هم زنجیر کنید بسیار راه‌دست است.

به عنوان مثلا اگر نیاز داشته باشید توکنی را بگیرد که با آن بتوانید یک مطلب وبلاگ را واکشی کنید از پایگاه داده و سپس اطلاعات نویسنده را به دست آورید:

> **توجه:** عبارت‌های *await* نیازمند آن است که داخل پرانتز قرار بگیرد تا بتوان متدها و خاصیت‌های مقدار حاصل شده‌اش در همان خط دست یافت.

```js
async function fetchPostById(postId) {
  const token = (await fetch('token_url')).json().token;
  const post = (await fetch(`/posts/${postId}?token=${token}`)).json();
  const author = (await fetch(`/users/${post.authorId}`)).json();

  post.author = author;
  return post;
}

fetchPostById('gzIrzeo64')
  .then(post => console.log(post))
  .catch(err => console.log(err));
```

##### مدیریت خطا

جز در حالتی که عبارت‌های *await* را داخل بلوک‌های *try / catch* قرار داده باشیم، خطاهایی که بروز می‌کنند (فارغ از این که در بدنه تابع *async* حادث شده باشد یا زمانی که حین *await* معلق شده باشد) وعده‌ای که توسط تابع async بازگردانده می‌شود رد خواهد شد. استفاده از دستور `throw` در تابع async درست همانند برگرداندن یک وعده رده‌شده است ([(مرجع: PonyFoo)](https://ponyfoo.com/articles/understanding-javascript-async-await#error-handling)).

> **توجه:** وعده‌ها مثل هم رفتار می‌کنند.

این جا روشی است که به کمکش می‌توانید خطاهای مرتبط با وعده‌ها را مدیریت کنید:

```js
function getUser() { // ‫این وعده رد خواهد شد!
  return new Promise((res, rej) => rej("User not found !"));
}

function getAvatarByUsername(userId) {
  return getUser(userId).then(user => user.avatar);
}

function getUserAvatar(username) {
  return getAvatarByUsername(username).then(avatar => ({ username, avatar }));
}

getUserAvatar('mbeaudru')
  .then(res => console.log(res))
  .catch(err => console.log(err)); // "User not found !"
```

معادل آن با *async / await*:

```js
async function getUser() { // وعده بازگردانده‌شده رد خواهد شد
  throw "User not found !";
}

async function getAvatarByUsername(userId) => {
  const user = await getUser(userId);
  return user.avatar;
}

async function getUserAvatar(username) {
  var avatar = await getAvatarByUsername(username);
  return { username, avatar };
}

getUserAvatar('mbeaudru')
  .then(res => console.log(res))
  .catch(err => console.log(err)); // "User not found !"
```

#### منابع خارجی

- [Async/Await - JavaScript.Info](https://javascript.info/async-await)
- [ES7 Async/Await](http://rossboucher.com/await/#/)
- [6 Reasons Why JavaScript’s Async/Await Blows Promises Away](https://hackernoon.com/6-reasons-why-javascripts-async-await-blows-promises-away-tutorial-c7ec10518dd9)
- [JavaScript awaits](https://dev.to/kayis/javascript-awaits)
- [Using Async Await in Express with Node 8](https://medium.com/@Abazhenov/using-async-await-in-express-with-node-8-b8af872c0016)
- [Async Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function)
- [Await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await)
- [Using async / await in express with node 8](https://medium.com/@Abazhenov/using-async-await-in-express-with-node-8-b8af872c0016)

### درستی / غلطی

در جاوااسکریپت، مقدار صحیح و غلط (true و false) مقداری است که در زمان ارزیابی در زمینه بولی، به مقدار بولی تبدیل می‌شود. به عنوان مثالی از زمینه بولی می‌توان به ارزیابی شرط `if` اشاره کرد.

هر مقداری به مقدار صحیح یا ‍`true` تبدیل می‌شود مگر آن که برابر باشد با یکی از موارد زیر:

- ```false```
- ```0```
- ```""``` (empty string)
- ```null```
- ```undefined```
- ```NaN```

این‌ها مثال‌هایی هستند از *مزینه بولی*:

- ارزیابی شرط `if`

```js
if (myVar) {}
```

مقدار `myVar` می‌تواند هر یک از شهروندان درجه یک یا [first-class citizen](https://en.wikipedia.org/wiki/First-class_citizen) (متغیر، تابع، بولی) باشد اما به مقدار بولی تبدیل می‌شود زیرا در یک زمینه بولی درحال ارزیابی شدن است.

- بعد از عملگر منطقی **NOT** یعنی `!`

اگر گزاره‌ای که این عملگر روی اعمال می‌شود قابل تبدیل شدن به true باشد، این عملگر باعث می‌شود که مقدار false برگردانده شود در غیر این صورت مقدار بازگشتی، true خواهد بود.

```js
!0 // true -- 0 is falsy so it returns true
!!0 // false -- 0 is falsy so !0 returns true so !(!0) returns false
!!"" // false -- empty string is falsy so NOT (NOT false) equals false
```

- با سازنده شیٔ بولی

```js
new Boolean(0) // false
new Boolean(1) // true
```

- در یک ارزیابی سه بخشی

```js
myVar ? "truthy" : "falsy"
```

اینجا myVar در حال ارزیابی شدن در یک زمینه بولی است.

زمانی که در حال مقایسه دو مقدار هستید مراقب باشید. مقادیر شیء (که باید تبدیل به true شوند) به مقدار بولی تبدیل **نمی‌شود* بلکه قهرا به واسطه [ToPrimitives specification](http://javascript.info/object-toprimitive) به مقدار اولیهٔ یک تبدیل می‌شوند. در اصل زمانی که یک شیء با یک مقدار بولی مانند ‬‪`[] == true`‬ مقایسه می‌شود، این عملیات رح مي‌دهد: ‪`[].toString() == true`

```js
let a = [] == true // a is false since [].toString() give "" back.
let b = [1] == true // b is true since [1].toString() give "1" back.
let c = [2] == true // c is false since [2].toString() give "2" back.
```

#### منابع خارجی

- [Truthy (MDN)](https://developer.mozilla.org/en-US/docs/Glossary/Truthy)
- [Falsy (MDN)](https://developer.mozilla.org/en-US/docs/Glossary/Falsy)
- [Truthy and Falsy values in JS - Josh Clanton](http://adripofjavascript.com/blog/drips/truthy-and-falsy-values-in-javascript.html)

### توابع Anamorphisms و Catamorphisms

#### تابع Anamorphisms

‫Anamorphisms توابع هستند که از برخشی اشیاء به ساختارهای پیچیده‌تری شامل نوع شیء نگاشت می‌شوند. فرایند گسترش یا *unfolding* یک ساختار ساده به یک ساختار پیچیده‌تر هستند. گسترش دادن یک عدد صحیح به فهرستی (list) از اعداد صحیح را در نظر بگیرید. عدد صحیح، شیء اولیه ماست و فهرست اعداد صحیح، آن ساختار پیچیده‌تر.


##### نمونه کد

```js
function downToOne(n) {
  const list = [];

  for (let i = n; i > 0; --i) {
    list.push(i);
  }

  return list;
}

downToOne(5)
  //=> [ 5, 4, 3, 2, 1 ]
```

#### تابع Catamorphisms

‫Catamorphisms نقطه مقابل Anamorphisms است و یک شیء با ساختاری پیچیده‌تر را به ساختاری ساده‌تر می‌کاهند. مثای بعدی را در نظر بگیرید که در آن، تابع `product` فهرستی از اعداد صحیح را گرفته و تنها یک عدد صحیح باز می‌گرداند.

##### نمونه کد

```js
function product(list) {
  let product = 1;

  for (const n of list) {
    product = product * n;
  }

  return product;
}

product(downToOne(5)) // 120
```

#### منابع خارجی

* [Anamorphisms in JavaScript](http://raganwald.com/2016/11/30/anamorphisms-in-javascript.html)
* [Anamorphism](https://en.wikipedia.org/wiki/Anamorphism)
* [Catamorphism](https://en.wikipedia.org/wiki/Catamorphism)

### تولیدکننده‌ها

راه دیگر نوشتن تابع `downToOne` استفاده از تولیدکننده‌ها یا Generatorهاست. برای برپاسازی یک شیء `Generator` می‌بایست از اعلان ‪`function *`‬ استفاده کنیم. تولیدکننده‌ها توابعی هستند که می‌شود از آن‌ها خارج و سپس وارد زمینه‌شان (متغیر گره‌خورده به‌شان) شد که در طول ورودها حفظ می‌شود.

به عنوان مثال می‌توانیم تابع `downToOne` را این گونه بازنویسی کنیم:

```js
function * downToOne(n) {
  for (let i = n; i > 0; --i) {
    yield i;
  }
}

[...downToOne(5)] // [ 5, 4, 3, 2, 1 ]
```

تابع تولیدکننده، یک شیء شمارش‌گر از بازمی‌گرداند. وقتی تابع ‪`Next()`‬ شمارش‌گر صدا زده می‌شود، تا رسیدن به عبارت `yield` (که مقدار مورد نظر برای بازگردانده شدن از آن شمارش به خصوص را تعیین می‌کند) و یا با ‪`yield*`‬ که به تابع تولید کننده دیگری اشاره می‌کند اجرا می‌شود. وقتی که عبارت `return` در تولیدکننده صدا زده می‌شود، تولیدکننده برچسب انجام شده دریافت می‌کند و مقدار تولید شده در آن شمارش بازگردانده می‌شود. فراخوانی‌های بعدی ‪`next()`‬ منجر به بازگرداندن مقادیر جدیدی نمی‌شود.
 
#### نمونه کد

```js
// Yield Example
function * idMaker() {
  var index = 0;
  while (index < 2) {
    yield index;
    index = index + 1;
  }
}

var gen = idMaker();

gen.next().value; // 0
gen.next().value; // 1
gen.next().value; // undefined
```

عبارت `yield` یک تولیدکننده را قادر می‌سازد تا در خلال شمارش، تابع تولیدکننده دیگری را فراخوانی کند.

```js
// Yield * Example
function * genB(i) {
  yield i + 1;
  yield i + 2;
  yield i + 3;
}

function * genA(i) {
  yield i;
  yield* genB(i);
  yield i + 10;
}

var gen = genA(10);

gen.next().valu
Download .txt
gitextract__fp8xgmi/

├── LICENSE
├── README.md
├── _config.yml
└── translations/
    ├── de-DE.md
    ├── fa-IR.md
    ├── fr-FR.md
    ├── ja-JP.md
    ├── pl_PL.md
    ├── pt-BR.md
    ├── ru-RU.md
    ├── th-TH.md
    ├── zh-CN.md
    └── zh-TW.md
Condensed preview — 13 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (604K chars).
[
  {
    "path": "LICENSE",
    "chars": 1071,
    "preview": "MIT License\n\nCopyright (c) 2017 BEAUDRU Manuel\n\nPermission is hereby granted, free of charge, to any person obtaining a "
  },
  {
    "path": "README.md",
    "chars": 66100,
    "preview": "# Modern JavaScript Cheatsheet\n\n![Modern JavaScript cheatsheet](https://i.imgur.com/aexPxMb.png)\n<sub>Image Credits: [Ah"
  },
  {
    "path": "_config.yml",
    "chars": 55,
    "preview": "theme: jekyll-theme-cayman\ntitle: Modern JS Cheatsheet\n"
  },
  {
    "path": "translations/de-DE.md",
    "chars": 71634,
    "preview": "# Modern JavaScript Cheatsheet\n\n![Modern JavaScript cheatsheet](https://i.imgur.com/aexPxMb.png)\n<sub>Bildnachweis: [Ahm"
  },
  {
    "path": "translations/fa-IR.md",
    "chars": 64494,
    "preview": "# برگه تقلب جاوااسکریپت مدرن\n\n## مقدمه\n\n### انگیزه\n\nاین سند، یک برگه تقلب برای مسائلی در جاوااسکپت است که به دفعات در کا"
  },
  {
    "path": "translations/fr-FR.md",
    "chars": 67222,
    "preview": "# Modern JavaScript Cheatsheet\n\n![Modern JavaScript cheatsheet](https://i.imgur.com/aexPxMb.png)\n<small>Crédits de l’ima"
  },
  {
    "path": "translations/ja-JP.md",
    "chars": 56614,
    "preview": "# <a name=\"modern-javascript-cheatsheet\"></a> モダン JavaScript チートシート\n\n![モダン JavaScript チートシート](https://i.imgur.com/aexPxM"
  },
  {
    "path": "translations/pl_PL.md",
    "chars": 67497,
    "preview": "# <a name=\"modern-javascript-cheatsheet\"></a>Współczesny JavaScript - ściągawka\n\n![Modern JavaScript cheatsheet](https:/"
  },
  {
    "path": "translations/pt-BR.md",
    "chars": 20015,
    "preview": "# Cheatsheet de JavaScript Moderno\n\n![Modern JavaScript cheatsheet](https://i.imgur.com/aexPxMb.png)\n<small>Crédito da I"
  },
  {
    "path": "translations/ru-RU.md",
    "chars": 68152,
    "preview": "# Памятка по современному JavaScript\n![Памятка по современному JavaScript](https://i.imgur.com/aexPxMb.png)\n<small>За ка"
  },
  {
    "path": "translations/th-TH.md",
    "chars": 56107,
    "preview": "# Modern JavaScript Cheatsheet\n\n![Modern JavaScript cheatsheet](https://i.imgur.com/aexPxMb.png)\n<small>เครดิตรูปภาพ: [A"
  },
  {
    "path": "translations/zh-CN.md",
    "chars": 8787,
    "preview": "# Modern JavaScript Cheatsheet 简体中文版\n\n![Modern JavaScript cheatsheet](https://i.imgur.com/aexPxMb.png)\n<small>Image Cred"
  },
  {
    "path": "translations/zh-TW.md",
    "chars": 35060,
    "preview": "<a name=\"#modern-javascript-cheatsheet\"></a>\n# Modern JavaScript Cheatsheet 繁體中文版\n\n![Modern JavaScript cheatsheet](https"
  }
]

About this extraction

This page contains the full source code of the mbeaudru/modern-js-cheatsheet GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 13 files (569.1 KB), approximately 179.0k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!