static - JavaScript

static
======

Baseline Widely available
-------------------------

This feature is well established and works across many devices and browser versions. It’s been available across browsers since March 2017.

* Learn more
* See full compatibility
* Report feedback
Для того, чтобы объявить статический метод класса, необходимо использовать ключевое слово **static**.

Синтаксис
---------
```

static methodName() { ... }
```

Описание
--------

Статические методы вызываются через имя класса. Вызывать статические методы через имя объекта запрещено. Статические методы часто используются для создания вспомогательных функций приложения.

Вызов статических методов
-------------------------

### Вызов из другого статического метода

Чтобы вызвать статический метод в другом статическом методе того же класса, вы можете использовать ключевое слово `this`.

```js
class StaticMethodCall {
  static staticMethod() {
    return "Вызван статический метод";
  }
  static anotherStaticMethod() {
    return this.staticMethod() + " из другого статического метода";
  }
}
StaticMethodCall.staticMethod();
// 'Вызван статический метод'

StaticMethodCall.anotherStaticMethod();
// 'Вызван статический метод из другого статического метода'
```

### Вызов из конструктора класса и других методов

Статические методы недоступны напрямую, используя ключевое слово `this` из нестатических методов. Вам нужно вызвать их с помощью имени класса: `CLASSNAME.STATIC_METHOD_NAME()` или вызовом метода как свойства конструктора: `this.constructor.STATIC_METHOD_NAME()`.

```js
class StaticMethodCall {
  constructor() {
    console.log(StaticMethodCall.staticMethod());
    // 'вызван статический метод.'

    console.log(this.constructor.staticMethod());
    // 'вызван статический метод.'
  }

  static staticMethod() {
    return "вызван статический метод.";
  }
}
```

Примеры
-------

Следующий пример демонстрирует:

1. Как статический метод реализуется в классе.
2. Как переопределить статический метод при наследовании.
3. Как можно и как нельзя вызывать статические методы.

```js
class Triple {
  static triple(n) {
    if (n === undefined) {
      n = 1;
    }
    return n \* 3;
  }
}

class BiggerTriple extends Triple {
  static triple(n) {
    return super.triple(n) \* super.triple(n);
  }
}

console.log(Triple.triple()); // 3
console.log(Triple.triple(6)); // 18

var tp = new Triple();

console.log(BiggerTriple.triple(3));
// 81 (не затрагивается экземпляром родителя)

console.log(tp.triple());
// Выведет сообщение, что "tripple" не является
// функцией ('tp.tripple is not a function').
```

Спецификации
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-class-definitions |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Смотрите также
--------------

* `class` expression
* `class` declaration
* Classes


Публичные поля классов - JavaScript

Публичные поля классов
======================

**Примечание:** Эта страница описывает экспериментальные возможности.

Публичные и приватные поля — это экспериментальная функция (stage
3), предложенная комитетом по стандарту JavaScript TC39.

Поддержка этой возможности в браузерах ограничена, но ее можно использовать посредством транспилирования с такими системами как Babel. Смотрите информацию о совместимости ниже.

И статические, и публичные поля являются изменяемыми, перечисляемыми, настраиваемыми свойствами. Таким образом, в отличие от приватных полей, они участвуют в прототипном наследовании.

Синтаксис
---------

```js
class ClassWithInstanceField {
  instanceField = "instance field";
}

class ClassWithStaticField {
  static staticField = "static field";
}

class ClassWithPublicInstanceMethod {
  publicMethod() {
    return "hello world";
  }
}
```

Примеры
-------

### Публичные статические поля

Публичные статические поля полезны тогда, когда необходимо существование одного единственного поля для всего класса, а не для каждого созданного экземпляра по отдельности. Это полезно для кеша, конфигураций или любых прочих данных, которые одинаковы для всех экземпляров.

Публичные статические поля объявляются при помощи ключевого слова `static`. Они добавляются в конструктор класса во время его создания с помощью `Object.defineProperty()`. Доступ также осуществляется через конструктор класса.

```js
class ClassWithStaticField {
  static staticField = "static field";
}

console.log(ClassWithStaticField.staticField);
// Ожидаемый вывод: "static field"
```

Поля без инициализации имеют значение `("javascript.classes")`.

```js
class ClassWithStaticField {
  static staticField;
}

console.assert(ClassWithStaticField.hasOwnProperty("staticField"));
console.log(ClassWithStaticField.staticField);
// Ожидаемый вывод: "undefined"
```

Публичные статические поля не переопределяются в наследниках класса, а могут быть доступны через иерархию прототипов.

```js
class ClassWithStaticField {
  static baseStaticField = "base field";
}

class SubClassWithStaticField extends ClassWithStaticField {
  static subStaticField = "sub class field";
}

console.log(SubClassWithStaticField.subStaticField);
// Ожидаемый вывод: "sub class field"

console.log(SubClassWithStaticField.baseStaticField);
// Ожидаемый вывод: "base field"
```

При определении полей `this` ссылается на конструктор класса. Также можно обратиться к нему по имени и использовать `super` для получения конструктора базового класса, если он существует.

```js
class ClassWithStaticField {
  static baseStaticField = "base static field";
  static anotherBaseStaticField = this.baseStaticField;

  static baseStaticMethod() {
    return "base static method output";
  }
}

class SubClassWithStaticField extends ClassWithStaticField {
  static subStaticField = super.baseStaticMethod();
}

console.log(ClassWithStaticField.anotherBaseStaticField);
// Ожидаемый вывод: "base static field"

console.log(SubClassWithStaticField.subStaticField);
// Ожидаемый вывод: "base static method output"
```

### Публичные поля экземпляра

Такие публичные поля имеются у каждого экземпляра данного класса. Объявляя публичные поля, мы можем гарантировать, что поле всегда присутствует, а объявление класса является более самодокументированным.

Публичные поля экземпляра добавляются через `Object.defineProperty()` либо перед тем, как будет исполнено тело конструктора в базовом классе, либо после того, как завершится `super()` в классе наследнике.

```js
class ClassWithInstanceField {
  instanceField = "instance field";
}

const instance = new ClassWithInstanceField();
console.log(instance.instanceField);
// Ожидаемый вывод: "instance field"
```

Поля без инициализации имеют значение `undefined`.

```js
class ClassWithInstanceField {
  instanceField;
}

const instance = new ClassWithInstanceField();
console.assert(instance.hasOwnProperty("instanceField"));
console.log(instance.instanceField);
// Ожидаемый вывод: "undefined"
```

Как и свойства, названия полей могут вычисляться.

```js
const PREFIX = "prefix";

class ClassWithComputedFieldName {
  [`${PREFIX}Field`] = "prefixed field";
}

const instance = new ClassWithComputedFieldName();
console.log(instance.prefixField);
// Ожидаемый вывод: "prefixed field"
```

При определении полей `this` ссылается на создающийся экземпляр класса. Как и в публичных методах экземпляра, получить доступ к прототипу базового класса можно с помощью `super`.

```js
class ClassWithInstanceField {
  baseInstanceField = "base field";
  anotherBaseInstanceField = this.baseInstanceField;
  baseInstanceMethod() {
    return "base method output";
  }
}

class SubClassWithInstanceField extends ClassWithInstanceField {
  subInstanceField = super.baseInstanceMethod();
}

const base = new ClassWithInstanceField();
const sub = new SubClassWithInstanceField();

console.log(base.anotherBaseInstanceField);
// Ожидаемый вывод: "base field"

console.log(sub.subInstanceField);
// Ожидаемый вывод: "base method output"
```

Публичные методы
----------------

### Публичные статические методы

Ключевое слово **`static`** объявляет статический метод класса. Статические методы не вызываются из экземпляра, вместо этого они вызывается из самого класса. Чаще всего это какие-либо служебные функции, такие как функции создания или копирования объектов.

```js
class ClassWithStaticMethod {
  static staticMethod() {
    return "static method has been called.";
  }
}

console.log(ClassWithStaticMethod.staticMethod());
// expected output: "static method has been called."
```

Статические методы добавляются в конструктор класса с помощью `Object.defineProperty()` во время его создания. Эти методы - изменяемые, неперечисляемые и настраиваемые свойства объекта.

### Публичные методы экземпляра

Как и следует из названия, публичные методы экземпляра это методы, доступные для вызова из экземпляров.

```js
class ClassWithPublicInstanceMethod {
  publicMethod() {
    return "hello world";
  }
}

const instance = new ClassWithPublicInstanceMethod();
console.log(instance.publicMethod());
// Ожидаемый вывод: "hello world"
```

Публичные методы добавляются в прототип класса во время его создания с помощью `Object.defineProperty()`. Они изменяемы, неперечисляемы и настраиваемы.

Вы можете использовать генераторы, асинхронные функции и асинхронные генераторы.

```js
class ClassWithFancyMethods {
  \*generatorMethod() {}
  async asyncMethod() {}
  async \*asyncGeneratorMethod() {}
}
```

 Внутри методов экземпляра, `this` ссылается на сам экземпляр.
 В классах наследниках, `super` даёт доступ к прототипу базового класса, позволяя вызывать его методы.

```js
class BaseClass {
  msg = "hello world";
  basePublicMethod() {
    return this.msg;
  }
}

class SubClass extends BaseClass {
  subPublicMethod() {
    return super.basePublicMethod();
  }
}

const instance = new SubClass();
console.log(instance.subPublicMethod());
// Ожидаемый вывод: "hello world"
```

Геттеры и сеттеры это специальные методы, которые привязаны к свойствам класса и которые вызываются, когда к свойству обращаются или записывают. Используйте get и set для объявления публичных геттеров и сеттеров экземпляра.

```js
class ClassWithGetSet {
  #msg = "hello world";
  get msg() {
    return this.#msg;
  }
  set msg(x) {
    this.#msg = `hello ${x}`;
  }
}

const instance = new ClassWithGetSet();
console.log(instance.msg);
// Ожидаемый вывод: "hello world"

instance.msg = "cake";
console.log(instance.msg);
// Ожидаемый вывод: "hello cake"
```

Спецификации
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-class-definitions |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Смотрите также
--------------

* Публичные и приватные поля классов статья на сайте v8.dev.
* Объявление полей класса в JavaScript, от авторов Публичных и приватных полей экземпляра
* Семантика всех элементов JS класса


Приватные поля класса - JavaScript

Приватные поля класса
=====================

Свойства класса по умолчанию являются общедоступными и могут быть рассмотрены или изменены вне класса. Тем не менее, есть экспериментальное предложение, позволяющее определить приватные поля класса, используя префикс хэша `#`.

Синтаксис
---------
```

class ClassWithPrivateField {
  #privateField
}

class ClassWithPrivateMethod {
  #privateMethod() {
    return 'hello world'
 }
}

class ClassWithPrivateStaticField {
  static #PRIVATE_STATIC_FIELD
}
```

Примеры
-------

### Приватные статические поля

Приватные поля доступны в конструкторе класса изнутри самой декларации класса.

Ограничение статических переменных, вызываемых только статическими методами, все ещё сохраняется.

```js
class ClassWithPrivateStaticField {
  static #PRIVATE\_STATIC\_FIELD;

  static publicStaticMethod() {
    ClassWithPrivateStaticField.#PRIVATE\_STATIC\_FIELD = 42;
    return ClassWithPrivateStaticField.#PRIVATE\_STATIC\_FIELD;
  }
}

console.assert(ClassWithPrivateStaticField.publicStaticMethod() === 42);
```

Приватные статические поля добавляются в конструктор класса во время обработки класса.

Существует ограничение по происхождению частных статических полей. Только класс, который определяет приватное статическое поле, может получить доступ к этому полю.

Это может привести к неожиданному поведению при использовании this.

```js
class BaseClassWithPrivateStaticField {
  static #PRIVATE\_STATIC\_FIELD;

  static basePublicStaticMethod() {
    this.#PRIVATE\_STATIC\_FIELD = 42;
    return this.#PRIVATE\_STATIC\_FIELD;
  }
}

class SubClass extends BaseClassWithPrivateStaticField {}

let error = null;

try {
  SubClass.basePublicStaticMethod();
} catch (e) {
  error = e;
}

console.assert(error instanceof TypeError);
```

### Приватные поля экземпляров

Приватные поля экземпляров объявляются **#имя** (произносится как "хэш нэймс"), которые идентифицируются префиксом **`#`**. `#` является частью имени, а также используется для объявления и доступа.

Инкапсуляция обеспечивается языком. Обращение к `#` именам вне области видимости является синтаксической ошибкой.

```js
class ClassWithPrivateField {
  #privateField;

  constructor() {
    this.#privateField = 42;
    this.#randomField = 666; // Syntax error
  }
}

const instance = new ClassWithPrivateField();
instance.#privateField === 42; // Syntax error
```

### Приватные методы

#### Приватные статические методы

Приватные статические методы

Как и их публичный эквивалент, приватные статические методы вызываются на самом классе, а не на экземплярах класса. Как и приватные статические поля, они доступны только изнутри объявления класса.

Приватные статические методы могут быть генераторами, асинхронными функциями и асинхронными функциями-генераторами.

```js
class ClassWithPrivateStaticMethod {
  static #privateStaticMethod() {
    return 42;
  }

  static publicStaticMethod1() {
    return ClassWithPrivateStaticMethod.#privateStaticMethod();
  }

  static publicStaticMethod2() {
    return this.#privateStaticMethod();
  }
}

console.assert(ClassWithPrivateStaticMethod.publicStaticMethod1() === 42);
console.assert(ClassWithPrivateStaticMethod.publicStaticMethod2() === 42);
```

Это может привести к неожиданному поведению при его использовании **`this`**. В следующем примере `this` относится к классу `Derived` (а не к классу `Base`), когда мы пытаемся вызвать `Derived.publicStaticMethod2()`, и, таким образом, имеет такое же "ограничение по происхождению", как упоминалось выше:

```js
class Base {
  static #privateStaticMethod() {
    return 42;
  }
  static publicStaticMethod1() {
    return Base.#privateStaticMethod();
  }
  static publicStaticMethod2() {
    return this.#privateStaticMethod();
  }
}

class Derived extends Base {}

console.log(Derived.publicStaticMethod1()); // 42
console.log(Derived.publicStaticMethod2()); // TypeError
```

#### Приватные методы экземпляров(instance)

Приватные методы экземпляров это методы, доступные у экземпляров класса, доступ к которым запрещён также, как у приватных полей класса.

```js
class ClassWithPrivateMethod {
  #privateMethod() {
    return "hello world";
  }

  getPrivateMessage() {
    return this.#privateMethod();
  }
}

const instance = new ClassWithPrivateMethod();
console.log(instance.getPrivateMessage());
// expected output: "hello world"
```

Приватные методы экземпляров могут быть генератором, async, или функциями async генератора. Приватные геттеры и сеттеры также возможны:

```js
class ClassWithPrivateAccessor {
  #message;

  get #decoratedMessage() {
    return `✨${this.#message}✨`;
  }
  set #decoratedMessage(msg) {
    this.#message = msg;
  }

  constructor() {
    this.#decoratedMessage = "hello world";
    console.log(this.#decoratedMessage);
  }
}

new ClassWithPrivateAccessor();
// expected output: "✨hello world✨"
```

Спецификации
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-class-definitions |

Совместимость с браузерами
--------------------------

### javascript.classes.private\_class\_fields

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

### javascript.classes.private\_class\_fields\_in

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

### javascript.classes.private\_class\_methods

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Смотрите также
--------------

* Public class fields
* The Semantics of All JS Class Elements


extends - JavaScript

extends
=======

Baseline Widely available
-------------------------

This feature is well established and works across many devices and browser versions. It’s been available across browsers since March 2017.

* Learn more
* See full compatibility
* Report feedback
Ключевое слово **`extends`** используется в объявлении класса или в выражениях класса для создания дочернего класса.

Синтаксис
---------
```

class ChildClass extends ParentClass { ... }
```

Описание
--------

Ключевое слово **`extends`** может быть использовано для создания дочернего класса для уже существующего класса или встроенного объекта.

Свойство **`.prototype`** родительского класса или объекта должно быть `Object` или `null`.

Примеры
-------

### Использование `extends`

В первом примере создаётся дочерний класс с именем `Square` от класса с именем `Polygon`. Этот пример был взят из live demo (source).

```js
class Square extends Polygon {
  constructor(length) {
    // Здесь вызывается конструктор родительского класса,
    // в который передаётся свойство length в качестве
    // аргументов, соответствующих полям width и height,
    // класса Polygon
    super(length, length);
    // Примечание:
    // В конструкторе класса, метод super() должен быть вызван
    // перед использованием this. В противном случае, будет
    // выброшена ошибка.
    this.name = "Square";
  }

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

### Расширение встроенных объектов с помощью `extends`

Этот пример расширяет встроенный объект `Date`. Пример взят из live demo (source).

```js
class myDate extends Date {
  constructor() {
    super();
  }

  getFormattedDate() {
    var months = [
      "Jan",
      "Feb",
      "Mar",
      "Apr",
      "May",
      "Jun",
      "Jul",
      "Aug",
      "Sep",
      "Oct",
      "Nov",
      "Dec",
    ];
    return (
      this.getDate() + "-" + months[this.getMonth()] + "-" + this.getFullYear()
    );
  }
}
```

### Расширение `null`

Расширение `null` работает как и с обычным классом, за исключением того, что прототип объекта не наследует `Object.prototype` (en-US).

```js
class nullExtends extends null {
  constructor() {}
}

Object.getPrototypeOf(nullExtends); // Function.prototype
Object.getPrototypeOf(nullExtends.prototype); // null

new nullExtends(); //ReferenceError: this is not defined
```

Спецификация
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-class-definitions |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Смотрите также
--------------

* Classes
* super


continue - JavaScript

continue
========

Сводка
------

Инструкция **continue** прерывает выполнение текущей итерации текущего или отмеченного цикла, и продолжает его выполнение на следующей итерации.

Синтаксис
---------
```

continue [ label ];
```

`label`

Идентификатор, являющийся меткой (`label`) инструкции.

Описание
--------

По сравнению с инструкцией `break`, `continue` прерывает выполнение цикла не полностью, вместо этого:

* В цикле `while` оно переносит поток выполнения к условию.

* В цикле `for` оно переносит поток выполнения к финальному выражению в описании цикла.

Инструкция `continue` может использоваться вместе с необязательной меткой, которая будет начинать следующую итерацию отмеченного цикла, а не текущего. В этом случае, `continue` должен находиться внутри отмеченного блока, который соответствует метке.

Примеры
-------

### Использование `continue` с циклом `while`

Пример показывает использование цикла `while` вместе с инструкцией `continue, которая выполняется, когда` `i` станет равно 3-м. Таким образом, `n` принимает значения 1, 3, 7 и 12.

```js
i = 0;
n = 0;
while (i < 5) {
  i++;
  if (i === 3) {
    continue;
  }
  n += i;
}
```

### Использование `continue` вместе с меткой

В примере цикл, отмеченный `checkiandj`, содержит внутри себя цикл, отмеченный `checkj`. Если встретится инструкция `continue`, выполнение кода продолжится в начале блока кода `checkj`. При каждом вызове `continue цикл` `checkj` будет начинать новую итерацию, пока условие не начнёт возвращать `false`. Когда это случится, продолжится выполнение оставшейся части цикла `checkiandj`.

Если бы `continue` имело метку `checkiandj`, программа продолжала бы свою работу с начала цикла `checkiandj`.

Смотрите также `label`.

```js
var i = 0,
  j = 8;

checkiandj: while (i < 4) {
  console.log("i: " + i);
  i += 1;

  checkj: while (j > 4) {
    console.log("j: " + j);
    j -= 1;
    if (j % 2 == 0) continue checkj;
    console.log(j + " является нечётным.");
  }
  console.log("i = " + i);
  console.log("j = " + j);
}
```

Вывод:

```js
"i: 0";

// начало checkj
"j: 8";
"7 является нечётным.";
"j: 7";
"j: 6";
"5 является нечётным.";
"j: 5";
// конец checkj

"i = 1";
"j = 4";

"i: 1";
"i = 2";
"j = 4";

"i: 2";
"i = 3";
"j = 4";

"i: 3";
"i = 4";
"j = 4";
```

Спецификации
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-continue-statement |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Смотрите также
--------------

* `break`
* `label`


Пустая инструкция - JavaScript

Пустая инструкция
=================

**Пустая инструкция** используется, когда инструкция не нужна, хотя синтаксис JavaScript будет предполагать её.

Синтаксис
---------
```

;
```

Описание
--------

Пустая инструкция - точка с запятой (;) оповещает о том, что ни одно выражение не будет выполняться, даже если синтаксис JavaScript ожидает этого.

Противоположное поведение, где вы хотите использовать несколько заявлений, но JavaScript позволяет только одно, можно сделать используя блок; он комбинирует несколько инструкций в одно.

Примеры
-------

Пустая инструкция используется в выражениях циклов. Смотрите следующий пример с пустым телом цикла:

```js
var arr = [1, 2, 3];

// Приравняет все значения массива к 0
for (i = 0; i < arr.length; arr[i++] = 0 /\* выражения \*/);

console.log(arr);
// [0, 0, 0]
```

**Заметьте:** Это хорошая идея: комментировать намеренное использование пустых инструкций, т.к. не очевидно отличить их от нормальной точки с запятой. В следующем примере использование, вероятно, ненамеренное:

```js
if (condition) // Внимание, этот if ничего не делает!
  killTheUniverse(); // Это всегда выполняется!!!
```

Другой пример: `if...else` без фигурных скобок (`{}`). Если `three` истинно, ничего не произойдёт, `four` не важна, и функция `launchRocket()` тоже не запустится.

```js
if (one) doOne();
else if (two) doTwo();
else if (three) // nothing here
else if (four) doFour();
else launchRocket();
```

Спецификации
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-empty-statement |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Смотрите также
--------------

* `Блок`


function* - JavaScript

function\*
==========

Сводка
------

**`function*`** (ключевое слово `function` со звёздочкой) определяет *функцию-генератор*.

Синтаксис
---------
```

function* name([param[, param[, ... param]]]) { statements }
```

`name`

Имя функции.

`param`

Именованные аргументы функции (параметры). Функция-генератор может иметь 255 аргументов.

`statements`

Инструкции составляющие тело функции.

Описание
--------

Генераторы являются функциями с возможностью выхода и последующего входа. Их контекст исполнения (значения переменных) сохраняется при последующих входах.

Когда вызывается функция-генератор, её тело исполняется не сразу; вместо этого возвращается объект-итератор. При вызове метода `next()` итератора тело функции-генератора исполняется до первого встреченного оператора **`yield`**, который определяет возвращаемое значение или делегирует дальнейшее выполнение другому генератору при помощи `yield* anotherGenerator()`. Метод `next()` возвращает объект со свойством `value`, содержащим отданное значение, и свойством `done`, которое указывает, что генератор уже отдал своё последнее значение. Вызов метода `next()` с аргументом прекращает выполнение функции-генератора, и заменяет инструкцию yield на которой было приостановлено выполнение на аргумент переданный в `next()`.

Примеры
-------

### Простой пример

```js
function\* idMaker() {
  var index = 0;
  while (index < 3) yield index++;
}

var gen = idMaker();

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

### Пример с yield\*

```js
function\* anotherGenerator(i) {
  yield i + 1;
  yield i + 2;
  yield i + 3;
}

function\* generator(i) {
  yield i;
  yield\* anotherGenerator(i);
  yield i + 10;
}

var gen = generator(10);

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

### Передача аргументов в генератор

```js
function\* logGenerator() {
  console.log(yield);
  console.log(yield);
  console.log(yield);
}

var gen = logGenerator();

// первый вызов next выполняется от начала функции
// и до первого оператора yield
gen.next();
gen.next("pretzel"); // pretzel
gen.next("california"); // california
gen.next("mayonnaise"); // mayonnaise
```

### Инструкция return в генераторе

```js
function\* yieldAndReturn() {
  yield "Y";
  return "R";
  yield "unreachable";
}

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

### Генераторы не могут быть инстанцированы (not constructable)

```js
function\* f() {}
var obj = new f(); // throws "TypeError: f is not a constructor"
```

Спецификации
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-generator-function-definitions |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Смотрите также
--------------

* Протокол итераторов
* Оператор yield
* Оператор function
* Другие ресурсы:
    + Компилятор Regenerator из ES2015 в ES5
    + Forbes Lindesay: Promises and Generators: control flow utopia — JSConf EU 2013
    + Task.js


for...of - JavaScript

for...of
========

Сводка
------

Оператор `for...of` выполняет цикл обхода итерируемых объектов (en-US) (включая `Array`, `Map` (en-US), `Set`, объект аргументов (en-US) и подобных), вызывая на каждом шаге итерации операторы для каждого значения из различных свойств объекта.

Синтаксис
---------
```

for (variable of iterable) {
  statement
}
```

`variable`

На каждом шаге итерации `variable` присваивается значение нового свойства объекта *`iterable`*. Переменная *`variable`* может быть также объявлена с помощью `const`, `let` или `var`.

`iterable`

Объект, перечисляемые свойства которого обходятся во время выполнения цикла.

Примеры
-------

### Обход `Array`
```

let iterable = [10, 20, 30];

for (let value of iterable) {
  value += 1;
  console.log(value);
}
// 11
// 21
// 31
```

Можно также использовать `const` вместо `let`, если не нужно переназначать переменные внутри блока.
```

let iterable = [10, 20, 30];

for (const value of iterable) {
  console.log(value);
}
// 10
// 20
// 30
```

### Обход `String`
```

let iterable = 'boo';

for (let value of iterable) {
  console.log(value);
}
// "b"
// "o"
// "o"
```

### Обход `TypedArray`
```

let iterable = new Uint8Array([0x00, 0xff]);

for (let value of iterable) {
  console.log(value);
}
// 0
// 255
```

### Обход `Map` (en-US)
```

let iterable = new Map([['a', 1], ['b', 2], ['c', 3]]);

for (let entry of iterable) {
  console.log(entry);
}
// ['a', 1]
// ['b', 2]
// ['c', 3]

for (let [key, value] of iterable) {
  console.log(value);
}
// 1
// 2
// 3
```

### Обход `Set`
```

let iterable = new Set([1, 1, 2, 2, 3, 3]);

for (let value of iterable) {
  console.log(value);
}
// 1
// 2
// 3
```

### Обход объекта `arguments`
```

(function() {
  for (let argument of arguments) {
    console.log(argument);
  }
})(1, 2, 3);

// 1
// 2
// 3
```

### Обход DOM коллекций

Обход DOM коллекций наподобие `NodeList`: следующий пример добавляет класс `read` параграфам, являющимся непосредственными потомками статей:
```

// Примечание: работает только на платформах, где
// реализован NodeList.prototype[Symbol.iterator]
let articleParagraphs = document.querySelectorAll('article > p');

for (let paragraph of articleParagraphs) {
  paragraph.classList.add('read');
}
```

### Закрытие итераторов

В циклах `for...of` аварийный выход осуществляется через `break`, `throw` или `return`. Во всех вариантах итератор завершается.
```

function* foo(){
  yield 1;
  yield 2;
  yield 3;
};

for (let o of foo()) {
  console.log(o);
  break; //  итератор закрывается, возврат
}
```

### Обход генераторов

Вы можете выполнять обход генераторов, вот пример:

```js
function\* fibonacci() {
  // функция-генератор
  let [prev, curr] = [0, 1];
  for (;;) {
    [prev, curr] = [curr, prev + curr];
    yield curr;
  }
}

for (let n of fibonacci()) {
  // ограничивает последовательность на 1000
  if (n > 1000) break;
  console.log(n);
}
```

#### Не пытайтесь повторно использовать генератор

Генераторы нельзя использовать дважды, даже если цикл `for...of` завершится аварийно, например, через оператор `break` . При выходе из цикла генератор завершается, и любые попытки получить из него значение обречены.

```js
var gen = (function\* () {
  yield 1;
  yield 2;
  yield 3;
})();
for (let o of gen) {
  console.log(o);
  break; // Завешение обхода
}

// Генератор нельзя повторно обойти, следующее не имеет смысла!
for (let o of gen) {
  console.log(o); // Не будет вызван
}
```

### Обход итерируемых объектов

Кроме того, можно сделать обход объекта, явно реализующего iterable:
```

var iterable = {
  [Symbol.iterator]() {
    return {
      i: 0,
      next() {
        if (this.i < 3) {
          return { value: this.i++, done: false };
        }
        return { value: undefined, done: true };
      }
    };
  }
};

for (var value of iterable) {
  console.log(value);
}
// 0
// 1
// 2
```

### Различия между `for...of` и `for...in`

Оба оператора, и `for...in` и `for...of` производят обход объектов . Разница в том, как они это делают.

Для `for...in` обход перечисляемых свойств объекта осуществляется в произвольном порядке.

Для `for...of` обход происходит в соответствии с тем, какой порядок определён в итерируемом объекте (en-US).

Следующий пример показывает различия в работе циклов `for...of` и `for...in` при обходе `Array`.
```

Object.prototype.objCustom = function() {};
Array.prototype.arrCustom = function() {};

let iterable = [3, 5, 7];
iterable.foo = 'hello';

for (let i in iterable) {
  console.log(i); // выведет 0, 1, 2, "foo", "arrCustom", "objCustom"
}

for (let i in iterable) {
  if (iterable.hasOwnProperty(i)) {
    console.log(i); // выведет 0, 1, 2, "foo"
  }
}

for (let i of iterable) {
  console.log(i); // выведет 3, 5, 7
}
```

Разберёмся шаг за шагом в вышеописанном коде.
```

Object.prototype.objCustom = function() {};
Array.prototype.arrCustom = function() {};

let iterable = [3, 5, 7];
iterable.foo = 'hello';
```

Каждый объект унаследует метод `objCustom` и каждый массив `Array` унаследует метод `arrCustom` благодаря созданию их в `Object.prototype` (en-US) и `Array.prototype`. Объект `iterable` унаследует методы `objCustom` и `arrCustom` из-за наследования через прототип.
```

for (let i in iterable) {
  console.log(i); // выведет 0, 1, 2, "foo", "arrCustom", "objCustom"
}
```

Цикл выводит только перечисляемые свойства объекта `iterable`, в порядке их создания. Он не выводит **значения** `3`, `5`, `7` и `hello` поскольку они **не являются** перечисляемыми, фактически они вообще не являются свойствами, они являются **значениями**. Выводятся же **имена свойств и методов**, например `arrCustom` и `objCustom`. Если вы ещё не совсем поняли, по каким свойствам осуществляется обход, вот дополнительное объяснение того, как работает `array iteration and for...in` .
```

for (let i in iterable) {
  if (iterable.hasOwnProperty(i)) {
    console.log(i); // выведет 0, 1, 2, "foo"
  }
}
```

Цикл аналогичен предыдущему, но использует `hasOwnProperty()` для проверки того, собственное ли это свойство объекта или унаследованное. Выводятся только собственные свойства. Имена `0`, `1`, `2` и `foo` принадлежат только экземпляру объекта (**не унаследованы**). Методы `arrCustom` и `objCustom` не выводятся, поскольку они **унаследованы**.
```

for (let i of iterable) {
  console.log(i); // выведет 3, 5, 7
}
```

Этот цикл обходит `iterable` и выводит те значения итерируемого объекта, которые определены в способе его перебора, т.е. не свойства объекта, а значения массива `3`, `5`, `7` .

Спецификации
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-for-in-and-for-of-statements |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Смотрите также
--------------

* `Array.prototype.forEach()`
* `Map.prototype.forEach()` (en-US)
* `Object.entries()`


do...while - JavaScript

do...while
==========

Выражение **`do...while`** создаёт цикл, который выполняет указанное выражение до тех пор, пока условие не станет ложным. Условие проверяется после выполнения выражения, то есть выражение выполнится как минимум один раз.

Интерактивный пример
--------------------

Синтаксис
---------
```

do
   выражение
while (условие);
```

`выражение`

Выражение, которое выполняется как минимум один раз и выполняется на каждом шаге цикла, пока условие истинно. Выражение может содержать несколько строк, для этого необходимо сгруппировать код в `блок` (`{ ... }`).

`условие`

Выражение, которое вычисляется после каждого шага цикла. Если `условие` истинно, то `выражение` выполняется ещё раз. Когда `условие` ложно, выполняется выражение, следующее после `do...while`.

Примеры
-------

### Использование `do...while`

В примере, цикл `do...while` выполняется до тех пор, пока `i` не перестанет быть меньше 5.

### HTML

```html
<div id="example"></div>
```

### JavaScript

```js
var result = "";
var i = 0;
do {
  i += 1;
  result += i + " ";
} while (i > 0 && i < 5); // Несмотря на то, что i == 0, цикл всё равно продолжится, так как начинается без теста
document.getElementById("example").innerHTML = result;
```

### Результат

Спецификации
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-do-while-statement |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Смотрите также
--------------

* `while`
* `for`


export - JavaScript

export
======

Инструкция **export** используется для экспорта функций, объектов или примитивов из файла (или модуля).

**Примечание:** Эта функциональность не реализована в браузерах на данный момент, но она реализована во многих транспайлерах, таких как Traceur Compiler, Babel or Rollup.

Синтаксис
---------
```

export { name1, name2, …, nameN };
export { variable1 as name1, variable2 as name2, …, nameN };
export let name1, name2, …, nameN; // или var
export let name1 = …, name2 = …, …, nameN; // или var, const

export default выражение;
export default function (…) { … } // или class, function*
export default function name1(…) { … } // или class, function*
export { name1 as default, … };

export * from …;
export { name1, name2, …, nameN } from …;
export { import1 as name1, import2 as name2, …, nameN } from …;
```

`nameN`

Идентификатор для экспорта (чтобы он мог быть импортирован с помощью `import` в другом файле (скрипте)).

Описание
--------

Существует два типа экспорта, каждый из которых описан ниже:

* Именованный экспорт:

```js
export { myFunction }; // экспорт ранее объявленной функции
export const foo = Math.sqrt(2); // экспорт константы
```

* Дефолтный экспорт (экспорт по умолчанию) (один на скрипт):

```js
export default function () {} // или 'export default class {}'
// тут не ставится точка с запятой
```

Именованная форма более применима для экспорта нескольких величин. Во время импорта, можно будет использовать одно и то же имя, чтобы обратиться к соответствующему экспортируемому значению.

Касательно экспорта по умолчанию (default), он может быть только один для каждого отдельного модуля (файла). Дефолтный экспорт может представлять собой функцию, класс, объект или что-то другое. Это значение следует рассматривать как "основное", так как его будет проще всего импортировать.

Примеры
-------

### Использование именованного экспорта

Мы могли бы использовать следующий код в модуле:

```js
// модуль"my-module.js"
function cube(x) {
  return x \* x \* x;
}
const foo = Math.PI + Math.SQRT2;
export { cube, foo };
```

Таким образом в другом скрипте при помощи импорта (см. `import`) мы могли бы получить следующее:

```js
import { cube, foo } from "my-module";
console.log(cube(3)); // 27
console.log(foo); // 4.555806215962888
```

### Использование export default

Если мы хотим экспортировать единственное значение или иметь резервное значение (fallback) для данного модуля, мы можем использовать `export default`.

```js
// модуль"my-module.js"
export default function cube(x) {
  return x \* x \* x;
}
```

Затем, в другом скрипте можно импортировать это значение по умолчанию таким образом:

```js
import cube from "my-module";
console.log(cube(3)); // 27
```

Спецификации
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-exports |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Смотрите также
--------------

* `import`
* ES6 in Depth: Modules, Hacks blog post by Jason Orendorff
* Axel Rauschmayer's book: "Exploring JS: Modules"


let - JavaScript

let
===

Директива **`let`** объявляет переменную с блочной областью видимости с возможностью инициализировать её значением.Синтаксис
---------
```

let var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]];
```

### Параметры

`var1`, `var2`, …, `varN`

Имя переменной. Может использоваться любой допустимый идентификатор.

`value1`, `value2`, …, `valueN`

Значение переменной. Любое допустимое выражение.

Описание
--------

Директива **`let`** позволяет объявить локальную переменную с областью видимости, ограниченной текущим блоком кода . В отличие от ключевого слова `var` (en-US), которое объявляет переменную глобально или локально во всей функции, независимо от области блока.

Объяснение, почему было выбрано название "**let**" можно найти здесь.

### Правила области видимости

Областью видимости переменных, объявленных ключевым словом `let`, является блок, в котором они объявлены, и все его подблоки. В этом работа директива `let` схожа с работой директивы `var`. Основная разница заключается в том, что областью видимости переменной, объявленной директивой `var`, является вся функция, в которой она объявлена:

```js
function varTest() {
  var x = 1;
  if (true) {
    var x = 2; // та же переменная!
    console.log(x); // 2
  }
  console.log(x); // 2
}

function letTest() {
  let x = 1;
  if (true) {
    let x = 2; // другая переменная
    console.log(x); // 2
  }
  console.log(x); // 1
}
```

### Чище код во вложенных функциях

`let` иногда делает код чище при использовании вложенных функций.

```js
var list = document.getElementById("list");

for (let i = 1; i <= 5; i++) {
  let item = document.createElement("li");
  item.appendChild(document.createTextNode("Item " + i));

  item.onclick = function (ev) {
    console.log("Item " + i + " is clicked.");
  };
  list.appendChild(item);
}

// чтобы получить такой же эффект с использованием 'var'
// необходимо создать новый контекст
// используя замыкание, чтобы сохранить значение неизменённым
for (var i = 1; i <= 5; i++) {
  var item = document.createElement("li");
  item.appendChild(document.createTextNode("Item " + i));

  (function (i) {
    item.onclick = function (ev) {
      console.log("Item " + i + " is clicked.");
    };
  })(i);
  list.appendChild(item);
}
```

Пример выше будет выполнен как и ожидается, так как пять экземпляров внутренней функции (анонимной) будут ссылаться на пять разных экземпляров переменной `i`. Пример будет выполнен неверно, если заменить директиву `let` на `var,` или удалить переменную `i` из параметров вложенной функции и использовать внешнюю переменную `i` во внутренней функции.

На верхнем уровне скриптов и функций `let, в отличии от var, не создаёт свойства на глобальном объекте`. Например:

```js
var x = "global\_x";
let y = "global\_y";
console.log(this.x); // 'global\_x'
console.log(this.y); // undefined
```

В выводе программы будет отображено слово "global\_x" для `this.x`, но `undefined` для `this.y`.

### Эмуляция приватных членов

При взаимодействии с конструкторами можно использовать выражение **`let`** чтобы открыть доступ к одному или нескольким приватным членам через использование замыканий:

```js
var SomeConstructor;

{
  let privateScope = {};

  SomeConstructor = function SomeConstructor() {
    this.someProperty = "foo";
    privateScope.hiddenProperty = "bar";
  };

  SomeConstructor.prototype.showPublic = function () {
    console.log(this.someProperty); // foo
  };

  SomeConstructor.prototype.showPrivate = function () {
    console.log(privateScope.hiddenProperty); // bar
  };
}

var myInstance = new SomeConstructor();

myInstance.showPublic();
myInstance.showPrivate();

console.log(privateScope.hiddenProperty); // error
```

Эта техника позволяет получить только "статичное" приватное состояние - в примере выше, все экземпляры полученные из конструктора `SomeConstructor` будут ссылаться на одну и ту же область видимости `privateScope`.

### Временные мёртвые зоны и ошибки при использовании `let`

Повторное объявление той же переменной в том же блоке или функции приведёт к выбросу исключения SyntaxError.

```js
if (x) {
  let foo;
  let foo; // SyntaxError thrown.
}
```

В стандарте ECMAScript 2015 переменные, объявленные директивой let, переносятся в начало блока. Но если вы сошлётесь в блоке на переменную, до того как она объявлена директивой let, то это приведёт к выбросу исключения `ReferenceError` (en-US), потому что переменная находится во "временной мёртвой зоне" с начала блока и до места её объявления. (В отличии от переменной, объявленной через `var`, которая просто будет содержать значение `undefined`)

```js
function do\_something() {
  console.log(bar); // undefined
  console.log(foo); // ReferenceError: foo is not defined
  var bar = 1;
  let foo = 2;
}
```

Вы можете столкнуться с ошибкой в операторах блока `switch` (en-US), так как он имеет только один подблок.

```js
switch (x) {
  case 0:
    let foo;
    break;

  case 1:
    let foo; // Выброс SyntaxError из-за повторного объявления переменной
    break;
}
```

### Использование `let` в циклах `for`

Вы можете использовать ключевое слово `let` для привязки переменных к локальной области видимости цикла `for`. Разница с использованием `var` в заголовке цикла `for`, заключается в том, что переменные объявленные `var`, будут видны во всей функции, в которой находится этот цикл.

```js
var i = 0;
for (let i = i; i < 10; i++) {
  console.log(i);
}
```

#### Правила области видимости

```js
for (let expr1; expr2; expr3) statement;
```

В этом примере *expr2*, \*expr3, statement \*заключены в неявный блок, который содержит блок локальных переменных, объявленных конструкцией `let expr1`. Пример приведён выше.

Примеры
-------

### `let` vs `var`

Когда let используется внутри блока, то область видимости переменной ограничивается этим блоком. Напомним, что отличие заключается в том, что областью видимости переменных, объявленных директивой var, является вся функция, в которой они были объявлены.

```js
var a = 5;
var b = 10;

if (a === 5) {
  let a = 4; // The scope is inside the if-block
  var b = 1; // The scope is inside the function

  console.log(a); // 4
  console.log(b); // 1
}

console.log(a); // 5
console.log(b); // 1
```

### `let` в циклах

Вы можете использовать ключевое слово `let` для привязки переменных к локальной области видимости цикла `for`, вместо того что бы использовать глобальные переменные (объявленные с помощью `var`).

```js
for (let i = 0; i < 10; i++) {
  console.log(i); // 0, 1, 2, 3, 4 ... 9
}

console.log(i); // i is not defined
```

Нестандартизированные расширения `let`
--------------------------------------

### `let` блок

**Предупреждение:** `Поддержка let` блоков была убрана в Gecko 44 Firefox bug 1023609.

**let блок** предоставляет способ, ассоциировать значения с переменными внутри области видимости этого блока, без влияния на значения переменных с теми же именами вне этого блока.

#### Синтаксис

```js
let (var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]]) block;
```

#### Описание

**`let`** блок предоставляет локальную область видимости для переменных. Работа его заключается в привязке нуля или более переменных к области видимости этого блока кода, другими словами, он является блоком операторов. Отметим, что область видимости переменных, объявленных директивой `var`, в **блоке `let`**, будет той же самой, что и если бы эти переменные были объявлены вне **блока `let`**, иными словами областью видимости таких переменных по-прежнему является функция. Скобки в **блоке `let`** являются обязательными. Опускание их приведёт к синтаксической ошибке.

#### Пример

```js
var x = 5;
var y = 0;

let (x = x+10, y = 12) {
  console.log(x+y); // 27
}

console.log(x + y); // 5
```

Правила для этого блока кода аналогичны как и для любого другого блока кода в JavaScript. Он может содержать свои локальные переменные, объявленные `let`.

#### Правила области видимости

Областью видимости переменных, объявленных директивой `let`, в **блоке** **`let`** является сам блок и все подблоки в нем, если они не содержат объявлений переменных с теми же именами.

### `let` выражения

**Предупреждение:** `Поддержка let выражений` была убрана в Gecko 41 Firefox bug 1023609.

**`let выражение`** позволяет объявить переменные с областью видимости ограниченной одним выражением.

#### Синтаксис
```

let (var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]]) expression;
```

#### Пример

Вы можете использовать let для объявления переменных, областью видимости которых является только одно выражение:

```js
var a = 5;
let(a = 6) console.log(a); // 6
console.log(a); // 5
```

#### Правила области видимости

В данном **`let` выражении**:

```js
let (decls) expr
```

\*`expr` \*оборачивается в неявный блок.

Спецификации
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-let-and-const-declarations |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


if...else - JavaScript

if...else
=========

**Инструкция if** выполняет инструкцию, если указанное условие выполняется (истинно). Если условие не выполняется (ложно), то может быть выполнена другая инструкция.

Синтаксис
---------
```

if (условие)
   инструкция1
[else
   инструкция2]
```

`условие`

Выражение, которое является либо истинным, либо ложным.

`инструкция1`

Инструкция, выполняемая в случае, если значение `"условиe"` истинно (`true`). Может быть любой инструкцией в том числе и вложенным `if`. Для группировки нескольких инструкций используется блок (`{...}`), Когда никакого действия не требуется, может использоваться пустая инструкция.

`инструкция2`

Инструкция, выполняемая в случае, если значение `"условиe"` ложно (`false`). Может быть любой инструкцией, в том числе и вложенным `if`. Инструкции тоже можно группировать в блок.

Описание
--------

Несколько команд if ... else могут быть вложены для создания условия `else if`. Обратите внимание, что в JavaScript нет ключевого слова `elseif` (в одно слово).
```

if (условие1)
   инструкция1
else if (условие2)
   инструкция2
else if (условие3)
   инструкция3
...
else
   инструкция
```

Чтобы увидеть, как это работает, ниже представлен пример правильного вложения с отступами:
```

if (условие1)
   инструкция1
else
   if (условие2)
      инструкция2
   else
      if (условие3)
...
```

Чтобы выполнить несколько инструкций в условии, используйте блочный оператор ({...}) для группирования этих инструкций. В общем, хорошей практикой всегда является использование блочных операторов, особенно в коде, включающем вложенные операторы `if`:
```

if (условие) {
   инструкции1
} else {
   инструкции2
}
```

Не путайте примитивные логические значения `true` и `false` с правдивостью или ложностью булева объекта. Любое значение, которое не `undefined`, `null`, `0`, `NaN` или пустая строка (""), и любой объект, включая объект Boolean, значение которого является ложным, считается правдивым при использовании в качестве условия. Например:

```js
var b = new Boolean(false);
if (b) // это условие истинно
```

Примеры
-------

### Использование `if...else`

```js
if (cipher_char === from_char) {
  result = result + to_char;
  x++;
} else {
  result = result + clear_char;
}
```

### Использование `else if`

Обратите внимание, что в JavaScript нет синтаксиса `elseif`. Однако вы можете записать его с пробелом между `else` и `if`:

```js
if (x > 5) {
} else if (x > 50) {
} else {
}
```

### Присваивание в условном выражении

Целесообразно не использовать простые присваивания в условном выражении, потому что при взгляде на код присваивание можно путать с равенством. Например, не используйте следующий код:

```js
if (x = y) {
  /\* сделать что-то \*/
}
```

Если вам нужно использовать присваивание в условном выражении, обычной практикой является размещение дополнительных скобок вокруг присваивания. Например:

```js
if ((x = y)) {
  /\* сделать что-то \*/
}
```

Спецификации
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-if-statement |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Смотрите также
--------------

* `block`
* `switch`


throw - JavaScript

throw
=====

Основная информация
-------------------

**Инструкция `throw`** позволяет генерировать исключения, определяемые пользователем. При этом выполнение текущей функции будет остановлено (инструкции после `throw` не будут выполнены), и управление будет передано в первый блок `catch` в стеке вызовов. Если `catch` блоков среди вызванных функций нет, выполнение программы будет остановлено.

Синтаксис
---------
```

throw выражение;
```

`выражение`

Определяемое пользователем исключение.

Описание
--------

Используйте инструкцию throw для генерирования исключения. Когда вы генерируете исключение (throw), *выражение* задаёт значение исключения. Каждое из следующих throw создаёт исключение:

```js
throw "Error2"; // генерирует исключение, значением которого является строка
throw 42; // генерирует исключение, значением которого является число 42
throw true; // генерирует исключение, значением которого является логическое значение true
```

Также стоит отметить, что на инструкцию `throw` влияет автоматическая вставка точки с запятой (ASI). Поэтому не допускаются разрывы строк между инструкцией `throw` и `выражением`.

Примеры
-------

### Пример: Генерирование объекта в качестве исключения

Можно указать объект в качестве исключения. Затем можно получить ссылку на этот объект и доступ ко всем его свойствам в блоке catch. Следующий пример создаёт объект ошибки, который имеет тип UserException, и используется для генерации исключения.

```js
function UserException(message) {
  this.message = message;
  this.name = "Исключение, определённое пользователем";
}
function getMonthName(mo) {
  mo = mo - 1; // Нужно скорректировать номер месяца согласно индексам массива (1 = Jan, 12 = Dec)
  const months = [
    "Jan",
    "Feb",
    "Mar",
    "Apr",
    "May",
    "Jun",
    "Jul",
    "Aug",
    "Sep",
    "Oct",
    "Nov",
    "Dec",
  ];
  if (months[mo] !== undefined) return months[mo];

  throw new UserException("Неверно указан номер месяца");
}

let monthName;

try {
  // statements to try
  const myMonth = 15; // 15 находится вне границ массива, что приведёт к исключению
  monthName = getMonthName(myMonth);
} catch (e) {
  monthName = "неизвестен";
  logMyErrors(e.message, e.name); // передаём исключение в обработчик ошибок
}
```

### Пример: Другой пример генерации объекта в виде исключения

Следующий пример проверяет, является ли строка, переданная в функцию, почтовым индексом США. Если индекс имеет недопустимый формат, будет сгенерировано исключение посредством создания объекта, имеющего тип `ZipCodeFormatException`.

```js
/\*
 \* Создаёт объект ZipCode.
 \*
 \* Допустимые форматы почтового индекса:
 \* 12345
 \* 12345-6789
 \* 123456789
 \* 12345 6789
 \*
 \* Если аргумент, переданный в конструктор ZipCode не совпадает
 \* ни с одним из этих форматов, будет брошено исключение.
 \*/

function ZipCode(zip) {
  zip = new String(zip);
  const pattern = /[0-9]{5}([- ]?[0-9]{4})?/;
  if (pattern.test(zip)) {
    // значение почтового индекса должно быть первым совпадением в строке
    this.value = zip.match(pattern)[0];
    this.valueOf = function () {
      return this.value;
    };
    this.toString = function () {
      return String(this.value);
    };
  } else {
    throw new ZipCodeFormatException(zip);
  }
}

function ZipCodeFormatException(value) {
  this.value = value;
  this.message = "Почтовый индекс имеет недопустимый формат";
  this.toString = function () {
    return this.value + this.message;
  };
}

/\*
 \* Это может быть скрипт, который проверяет значение адреса
 \* для США.
 \*/

const ZIPCODE\_INVALID = -1;
const ZIPCODE\_UNKNOWN\_ERROR = -2;

function verifyZipCode(z) {
  try {
    z = new ZipCode(z);
  } catch (e) {
    return e instanceof ZipCodeFormatException
      ? ZIPCODE\_INVALID
      : IPCODE\_UNKNOWN\_ERROR;
  }
  return z;
}

a = verifyZipCode(95060); // вернёт 95060
b = verifyZipCode(9560); // вернёт -1
c = verifyZipCode("a"); // вернёт -1
d = verifyZipCode("95060"); // вернёт 95060
e = verifyZipCode("95060 1234"); // вернёт 95060 1234
```

### Пример: Повторный выброс исключения

Можно использовать throw для повторного выброса исключения после того, как оно было поймано. В следующем примере ловится исключение с числовым значением и делается повторный выброс, если его значение больше 50. Повторно выброшенное исключение передаётся далее в вызывающую функцию или до верхнего уровня, который видит пользователь.

```js
try {
  throw n; // бросаем исключение с числовым значением
} catch (e) {
  if (e <= 50) {
    // инструкции для обработки исключений со значениями в диапазоне 1-50
  } else {
    // необработанное исключение, делаем повторный выброс
    throw e;
  }
}
```

Спецификации
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-throw-statement |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Смотрите также
--------------

* `try...catch`


var - JavaScript

var
===

Оператор **var** объявляет переменную, инициализируя её, при необходимости.

Интерактивный пример
--------------------

Синтаксис
---------
```

var varname1 [= value1 [, varname2 [, varname3 ... [, varnameN]]]];
```

`varnameN`

Имя переменной. Может использоваться любой допустимый идентификатор.

`valueN`

Значение переменной. Любое допустимое выражение. По умолчанию значение *undefined.*

Описание
--------

Объявление переменной всегда обрабатывается до выполнения кода, где бы она ни находилась. Область видимости переменной, объявленной через `var`, это её текущий *контекст выполнения*. Который может ограничиваться функцией или быть глобальным, для переменных, объявленных за пределами функции.

Присвоение значения необъявленной переменной подразумевает, что она будет создана как глобальная переменная (переменная становится свойством глобального объекта) после выполнения присваивания значения. Различия между объявленной и необъявленной переменными следующие:

1. Объявленные переменные ограничены контекстом выполнения, в котором они были объявлены. Необъявленные переменные всегда глобальны.

```js
function x() {
  y = 1; // возбудит ReferenceError в "строгом режиме"
  var z = 2;
}

x();

console.log(y); // выведет "1"
console.log(z); // возбудит ReferenceError: z не определён вне x
```

2. Объявленные переменные инициализируются до выполнения любого кода. Необъявленные переменные не существуют до тех пор, пока к ним не выполнено присваивание.

```js
console.log(a); // Возбудит ReferenceError.
console.log("still going..."); // Не выполнится.
```

```js
var a;
console.log(a); // Выведет "undefined" или "", в зависимости от браузера.
console.log("still going..."); // Выведет "still going...".
```

3. Объявленные переменные, независимо от контекста выполнения, являются ненастраиваемыми свойствами. Необъявленные переменные это настраиваемые свойства (т.е. их можно удалять).

```js
var a = 1;
b = 2;

delete this.a; // Возбудит TypeError в "строгом режиме". В "нестрогом режиме" будет ошибка без уведомления.
delete this.b;

console.log(a, b); // Возбудит ReferenceError.
// Свойство 'b' было удалено и больше не существует.
```

Из-за перечисленных различий, использование необъявленных переменных может привести к непредсказуемым последствиям. **Рекомендовано всегда объявлять переменные, вне зависимости, находятся они внутри функции или в глобальном контексте.** Присваивание значения необъявленной переменной в строгом режиме (en-US) ECMAScript 5 возбуждает ошибку.

### Поднятие переменных

Объявление переменных (как и любые другие объявления) обрабатываются до выполнения кода. Где бы не находилось объявление, это равнозначно тому, что переменную объявили в самом начале кода. Это значит, что переменная становится доступной до того, как она объявлена. Такое поведение называется "поднятием" (в некоторых источниках "всплытием").

```js
bla = 2;
var bla;
// ...

// читается как:

var bla;
bla = 2;
```

Поэтому объявление переменных рекомендовано выносить в начало их области видимости (в начало глобального кода или в начало функции). Это даёт понять какие переменные принадлежат функции (т.е. являются локальными), а какие обрабатываются в цепи областей видимости (т.е. являются глобальными).

Важно отметить, что подъем будет влиять на объявление переменной, но не на инициализацию её значения. Значение присваивается при выполнении оператора присваивания:

```js
function do\_something() {
  console.log(bar); // выведет undefined
  var bar = 111;
  console.log(bar); // выведет 111
}

// ...неявно понимается как:

function do\_something() {
  var bar;
  console.log(bar); // выведет undefined
  bar = 111;
  console.log(bar); // выведет 111
}
```

Примеры
-------

### Объявление и инициализация двух переменных

```js
var a = 0,
  b = 0;
```

### Присвоение двум переменным одного строкового значения

```js
var a = "A";
var b = a;

// Равнозначно:

var a,
  b = (a = "A");
```

Следите за порядком присвоения значений переменным

```js
var x = y,
  y = "A";
console.log(x + y); // undefinedA
```

В примере, `x` и `y` объявлены до выполнение кода, присвоение выполняется позже. Когда происходит присваивание "`x = y`", `y` уже существует со значением '`undefined`', так что ошибка `ReferenceError` не генерируется. И переменной `x` присваивается неопределённое значение. Потом переменной `y` присваивается значение 'A'. Получается, что после выполнения первой строки кода `x === undefined && y === 'A'`, отсюда и результат.

### Инициализация нескольких переменных

```js
var x = 0;

function f() {
  var x = (y = 1); // x - объявляется локально. y - глобально!
}
f();

console.log(x, y); // 0, 1
// значение x взято из глобальной переменной, как и ожидалось
// значение переменной y доступно глобально
```

Такой же пример, но в строгом режиме:

```js
"use strict";

var x = 0;
function f() {
  var x = (y = 1); // Throws a ReferenceError in strict mode.
}
f();

console.log(x, y);
```

### Неявные глобальные переменные и внешняя область видимости

Переменные могут ссылаться на переменные внешней области видимости функции, и это может выглядеть неявно:

```js
var x = 0; // x объявлена глобально, затем присваивается значение 0

console.log(typeof z); // undefined, пока ещё z не существует

function a() {
  // когда функция a вызвана,
  var y = 2; // y объявляется локально в функции a, затем присваивается 2

  console.log(x, y); // 0 2

  function b() {
    // когда функция b вызвана
    x = 3; // присваивается 3 существующей глобальной x
    y = 4; // присваивается 4 существующей внешней y
    z = 5; // создаётся новая глобальная переменная z и присваивается значение 5.
  } // (Порождает ReferenceError в strict mode(строгом режиме).)

  b(); // вызов b создаёт z как глобальную переменную
  console.log(x, y, z); // 3 4 5
}

a(); // вызов a также вызывает b
console.log(x, z); // 3 5
console.log(typeof y); // undefined, так как y это локальная переменная для функции a
```

Спецификации
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-variable-statement |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Смотрите также
--------------

* `let`
* `const`
* How One Missing `var` Ruined our Launch


with - JavaScript

with
====

**Предупреждение:** Использование оператора `with` не рекомендуемо, т.к. он может быть источником запутанных багов и проблем совместимости. Детальная информация в параграфе "Ambiguity Contra" раздела "Description".

Инструкция **with** расширяет цепочку областей видимости для инструкции.

Синтаксис
---------
```

with (expression)
  statement
```

`expression`

Добавляет данный exrpession в цепочку областей видимости используемое когда исследуется statement. Рекомендуется использовать круглые скобки вокруг выражения.

`statement`

Любое выражение. Чтобы использовать несколько выражений, используйте оператор block statement ({ ... }), чтобы сгруппировать их.

Описание
--------

JavaScript ищет unqualified имя, исследуя цепочку областей видимости, связанную с выполнением скрипта или функции, содержащих это unqualified имя. Оператор 'with' добавляет данный объект в начало цепочки областей видимости в ходе исследования тела его оператора. Если unqualified имя используемое в теле соответствует свойству в цепочке областей видимости, тогда имя привязывается к свойству и объекту, содержащему это свойство. В противном случае возвращается `ReferenceError`.

**Примечание:** Использование оператора `with` не рекомендуется, и недопустимо в строгом режиме (strict mode (en-US)) ECMAScript 5 . Рекомендуемой альтернативой может стать связывание объекта, чьи свойства Вы хотели получить, с коротким именем переменной.

### Performance pro & contra

**Pro:** Оператор **with** может помочь уменьшить размер файла, уменьшив необходимость повторять длинную ссылку на объект без снижения производительности. Изменение цепочки контекста, необходимое для 'with', не требует больших вычислительных затрат. Использование 'with' избавит интерпретатор от разбора повторных ссылок на объекты. Однако, обратите внимание, что во многих случаях это преимущество может быть достигнуто с помощью временной переменной для хранения ссылки на нужный объект.

**Contra:** Оператор **with** заставляет указанный объект быть найденным сначала среди всех имён поиска. Поэтому все идентификаторы, которые не относятся к указанному объекту, будут обнаруживаться медленнее в блоке «**with**. Там, где важна производительность, «with» следует использовать только для охвата блоков кода, которые обращаются к членам указанного объекта.

### Ambiguity contra

**Contra:** The `with` statement makes it hard for a human reader or JavaScript compiler to decide whether an unqualified name will be found along the scope chain, and if so, in which object. So given this example:

```js
function f(x, o) {
  with (o) {
    console.log(x);
  }
}
```

Only when `f` is called is `x` either found or not, and if found, either in `o` or (if no such property exists) in `f`'s activation object, where `x` names the first formal argument. If you forget to define `x` in the object you pass as the second argument, or if there's some similar bug or confusion, you won't get an error — just unexpected results.

**Contra:** Code using `with` may not be forward compatible, especially when used with something other than a plain object. Consider this example:

```js
function f(foo, values) {
  with (foo) {
    console.log(values);
  }
}
```

If you call `f([1,2,3], obj)` in an ECMAScript 5 environment, then the `values` reference inside the `with` statement will resolve to `obj`. However, ECMAScript 6 introduces a `values` property on `Array.prototype` (so that it will be available on every array). So, in a JavaScript environment that supports ECMAScript 6, the `values` reference inside the `with` statement will resolve to `[1,2,3].values`.

Примеры
-------

### Использование `with`

Последующее использование **`with`** указывает что Объект `Math` является объектом по умолчанию. Следующие инструкции за **`with`** ссылаются на свойства `PI` и методы [`cos`]](/ru/docs/Web/JavaScript/Reference/Global\_Objects/Math/cos) и [`sin`]](/ru/docs/Web/JavaScript/Reference/Global\_Objects/Math/sin), без указания объекта. JavaScript предполагает Объект `Math` для этих справок.

```js
var a, x, y;
var r = 10;

with (Math) {
  a = PI \* r \* r;
  x = r \* cos(PI);
  y = r \* sin(PI / 2);
}
```

Спецификации
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-with-statement |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Смотрите также
--------------

* `block`
* Strict mode (en-US)
* `Symbol.unscopables`
* `Array.prototype[@@unscopables]`


Блок - JavaScript

Блок
====

**Блок инструкций** (или **сложная инструкция** в других языках) используется для группировки нуля или более инструкций. Блок отделяется парой фигурных скобок и может опционально быть `поименован`:

Синтаксис
---------
```

[имя:] {
  инструкция_1;
  инструкция_2;
  ...
  инструкция_n;
}
```

`инструкция_1`, `инструкция_2`, `инструкция_n`

Инструкции, сгруппированные внутри блока инструкций.

имя

Необязательное `имя` для визуальной идентификации или использования как точки выхода для оператора `break`.

Описание
--------

Эта инструкция широко используется с операторами управления потоком (н., `if...else`, `for`, `while`). Например:

```js
while (x < 10) {
  x++;
}
```

Обратите внимание, что блок инструкций не заканчивается точкой с запятой.

Блок инструкций часто называется **сложной (составной) инструкцией** в других языках. Он позволяет вам использовать несколько операторов там, где JavaScript ожидает один оператор. Помещение инструкций в блок - это распространённая практика в JavaScript. Противоположное поведение - использование пустого оператора там, где никаких действий не нужно, а оператор требуется.

### Правила области видимости блока

#### С использованием `var`

Переменные, объявленные через `var`, **не** **имеют** блочной области видимости. Переменные, введённые внутри блока, имеют областью видимости содержащую их функцию или скрипт, и последствия записи в них значения распространяются за границы, собственно, блока, в котором они объявлены. Другими словами, блок инструкций не вводит новую область видимости. Хотя "отдельно стоящие" блоки не являются нарушением синтаксиса, не стоит использовать отдельно стоящие блоки в JavaScript, потому что они не делают то, чего вы от них ожидаете, если вы ожидаете, что они будут себя вести аналогично блокам в C или Java. Например:

```js
var x = 1;
{
  var x = 2;
}
console.log(x); // выводит 2
```

Тут выводится 2, потому что оператор `var x` внутри блока - в той же области видимости, что и оператор `var x` перед блоком. В C или Java подобный код вывел бы 1.

#### С `let` и `const`

Наоборот, идентификаторы, объявленные с помощью `let` и `const` **имеют** блочную область видимости:

```js
let x = 1;
{
  let x = 2;
}
console.log(x); // выводит 1
```

`x = 2` ограничено рамками области видимости блока, в котором оно было определено.

То же самое и для `const`:

```js
const c = 1;
{
  const c = 2;
}
console.log(c); // выводит 1 и не выбрасывает SyntaxError...
```

Обратите внимание, что объявленная внутри блока `const c = 2` *не* кидает `SyntaxError: Identifier 'c' has already been declared` (`идентификатор 'c' уже был объявлен`) потому что она может быть объявлена единожды внутри блока.

Спецификации
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-block |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Смотрите также
--------------

* `while`
* `if...else`
* `let`


for await...of - JavaScript

for await...of
==============

Выражение **`for await...of`** создаёт цикл, проходящий через асинхронные итерируемые объекты, а также синхронные итерируемые сущности, включающие: встроенные `String`, `Array`, `Array`-подобные объекты (например., `arguments` или `NodeList`), `TypedArray`, `Map` (en-US), `Set`, а также определяемые пользователем асинхронные/синхронные сущности. Он вызывает пользовательский итерационный хук с инструкциями, которые должны быть выполнены для значения каждого отдельного свойства объекта.

Синтаксис
---------
```

for await (variable of iterable) {
  statement
}
```

`variable`

На каждой итерации значение другого свойства присваивается *variable*. *variable* может быть объявлена с помощью ключевых слов `const`, `let`, or `var`.

`iterable`

Объект, чьи итерируемые свойства будут повторяться.

### Итерирование по асинхронным переменным

Вы также можете перебрать объект, который явно реализует асинхронный итерируемый протокол.

```js
var asyncIterable = {
  [Symbol.asyncIterator]() {
    return {
      i: 0,
      next() {
        if (this.i < 3) {
          return Promise.resolve({ value: this.i++, done: false });
        }

        return Promise.resolve({ done: true });
      },
    };
  },
};

(async function () {
  for await (let num of asyncIterable) {
    console.log(num);
  }
})();

// 0
// 1
// 2
```

### Итерирование по асинхронным генераторам

Поскольку асинхронные генераторы реализуют асинхронный протокол Iterator, по ним можно пройти циклом с помощью `for await... of`

```js
async function\* asyncGenerator() {
  var i = 0;
  while (i < 3) {
    yield i++;
  }
}

(async function () {
  for await (let num of asyncGenerator()) {
    console.log(num);
  }
})();
// 0
// 1
// 2
```

Для более конкретного примера перебора асинхронного генератора с помощью `for await... of`, рассмотрим перебор данных из API. В этом примере сначала создаётся асинхронный итератор для потока данных, а затем он используется для определения размера ответа от API.

```js
async function\* streamAsyncIterator(stream) {
  const reader = stream.getReader();
  try {
    while (true) {
      const { done, value } = await reader.read();
      if (done) {
        return;
      }
      yield value;
    }
  } finally {
    reader.releaseLock();
  }
}
// Fetches data from url and calculates response size using the async generator.
async function getResponseSize(url) {
  const response = await fetch(url);
  // Will hold the size of the response, in bytes.
  let responseSize = 0;
  // The for-await-of loop. Async iterates over each portion of the response.
  for await (const chunk of streamAsyncIterator(response.body)) {
    // Incrementing the total response length.
    responseSize += chunk.length;
  }

  console.log(`Response Size: ${responseSize} bytes`);
  // expected output: "Response Size: 1071472"
  return responseSize;
}
getResponseSize("https://jsonplaceholder.typicode.com/photos");
```

Спецификации
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-for-in-and-for-of-statements |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Смотрите также
--------------

* `Statements/for...of`


import - JavaScript

import
======

Инструкция **import** используется для импорта ссылок на значения, экспортированные из внешнего модуля. Импортированные модули находятся в `строгом режиме` независимо от того, объявляете ли вы их как таковые или нет. Для работы инструкции во встроенных скриптах нужно прописать у тэга script `type="module"`.

Существует также function-like динамический `import()`, который не требует скриптов с типом "`module`".

Обратная совместимость может быть обеспечена с помощью атрибута `nomodule` тега script.

Динамический импорт полезен в ситуациях, когда вы хотите загрузить модуль условно или по требованию. Статическая форма предпочтительна для загрузки начальных зависимостей и может быть более полезна для инструментов статического анализа и tree shaking (en-US).

**Примечание:** На данный момент эта функциональность только начинает поддерживаться браузерами. Полноценная реализация присутствует во многих транспайлерах, таких как TypeScript и Babel, а также в сборщиках, например, в Rollup и Webpack.

Синтаксис
---------
```

import defaultExport from "module-name";
import * as name from "module-name";
import { export } from "module-name";
import { export as alias } from "module-name";
import { export1 , export2 } from "module-name";
import { export1 , export2 as alias2 , […] } from "module-name";
import defaultExport, { export [ , […] ] } from "module-name";
import defaultExport, * as name from "module-name";
import "module-name";
import("/module-name.js").then(module => {…}) // Динамический импорт
```

`defaultExport`

Имя объекта, который будет ссылаться на значение экспорта по умолчанию (дефолтный экспорт) из модуля.

`module-name`

Имя модуля для импорта. Это зачастую относительный или абсолютный путь к `.js` файлу модуля без указания расширения `.js`. Некоторые сборщики могут разрешать или даже требовать использования расширения; проверяйте своё рабочее окружение. Допускаются только строки с одиночными или двойными кавычками.

`name`

Имя локального объекта, который будет использован как своего рода пространство имён, ссылающееся на импортируемые значения.

`export, exportN`

Имена значений, которые будут импортированы.

`alias, aliasN`

Имена, которые будут ссылаться на импортируемые значения.

Описание
--------

Параметр `name` это имя локального объекта, который будет использован как своего рода пространство имён, ссылающееся на импортируемые значения. Параметры `export` определяют отдельные именованные значения, в то время как `import * as name` импортирует все значения. Примеры ниже объясняют синтаксис.

### Импорт всего содержимого модуля

Этот код вставляет объект `myModule` в текущую область видимости, содержащую все экспортированные значения из модуля, находящегося в файле `/modules/my-module.js`.

```js
import \* as myModule from "/modules/my-module.js";
```

В данном случае, доступ к импортируемым значениям можно осуществить с использованием имени модуля (в данном случае "myModule") в качестве пространства имён. Например, если импортируемый выше модуль включает в себя экспорт метода `doAllTheAmazingThings()`, вы можете вызвать его так:

```js
myModule.doAllTheAmazingThings();
```

### Импорт единичного значения из модуля

Определённое ранее значение, названное `myExport,` которое было экспортировано из модуля `my-module` либо неявно (если модуль был экспортирован целиком), либо явно (с использованием инструкции `export`), позволяет вставить `myExport` в текущую область видимости.

```js
import { myExport } from "/modules/my-module.js";
```

### Импорт нескольких единичных значений

Этот код вставляет оба значения `foo` и `bar` в текущую область видимости.

```js
import { foo, bar } from "/modules/my-module.js";
```

### Импорт значений с использованием более удобных имён

Вы можете переименовать значения, когда импортируете их. Например, этот код вставляет `shortName` в текущую область видимости.

```js
import { reallyReallyLongModuleExportName as shortName } from "/modules/my-module.js";
```

### Переименование нескольких значений в одном импорте

Код, который импортирует несколько значений из модуля, используя более удобные имена.

```js
import {
  reallyReallyLongModuleExportName as shortName,
  anotherLongModuleName as short,
} from "/modules/my-module.js";
```

### Импорт модуля для использования его побочного эффекта

Импорт всего модуля только для использования побочного эффекта от его вызова, не импортируя что-либо. Это запускает глобальный код модуля, но в действительности не импортирует никаких значений.

```js
import "/modules/my-module.js";
```

### Импорт значения по умолчанию

Есть возможность задать дефолтный `export` (будь то объект, функция, класс или др.). Инструкция `import` затем может быть использована для импорта таких значений.

Простейшая версия прямого импорта значения по умолчанию:

```js
import myDefault from "/modules/my-module.js";
```

Возможно также использование такого синтаксиса с другими вариантами из перечисленных выше (импорт пространства имён или именованный импорт). В таком случае, импорт значения по умолчанию должен быть определён первым. Для примера:

```js
import myDefault, \* as myModule from "/modules/my-module.js";
// myModule использовано как пространство имён
```

или

```js
import myDefault, { foo, bar } from "/modules/my-module.js";
// именованный импорт конкретных значений
```

### Импорт переменных

Если вы импортируете переменные, то в данной области видимости они ведут себя как константы.

Такой код выведет ошибку:

* my-module.js:

```js
export let a = 2;
export let b = 3;
```

* main.js:

```js
import { a, b } from "/modules/my-module.js";
a = 5;
b = 6;
// Uncaught TypeError: Assignment to constant variable.
```

Для импорта можно воспользоваться объектом в котором хранятся эти переменные.

Такой код будет рабочим:

* my-module.js:

```js
export let obj = { a: 2, b: 4 };
```

* main.js:

```js
import { obj } from "/modules/my-module.js";

obj.a = 1;
obj.b = 4;
```

Учитывая, что `import` хранит именно ссылки на значения, экспортированные из внешнего модуля, то это можно использовать как замыкания.

### Динамический импорт

Ключевое слово `import` можно использовать как функцию для динамического импорта модулей. Вызов `import()` возвращает Promise.

```js
import("/modules/my-module.js").then((module) => {
  // Делаем что-нибудь с модулем
});
```

Как следствие возврата Promise, с динамическим импортом можно использовать ключевое слово `await`

```js
let module = await import("/modules/my-module.js");
```

Обратите внимание, что несмотря на то, что динамический импорт выглядит как вызов функции, он им по сути не является, т.е. не наследует от `Function.prototype` и, как следствие, его невозможно использовать вместе с методами `.call`, `.apply` и `.bind`

Примеры
-------

Импорт из вспомогательного модуля для помощи в обработке запроса AJAX JSON.

### Модуль: file.js

```js
function getJSON(url, callback) {
  let xhr = new XMLHttpRequest();
  xhr.onload = function () {
    callback(this.responseText);
  };
  xhr.open("GET", url, true);
  xhr.send();
}

export function getUsefulContents(url, callback) {
  getJSON(url, (data) => callback(JSON.parse(data)));
}
```

### Основной код: main.js

```js
import { getUsefulContents } from "/modules/file.js";

getUsefulContents("http://www.example.com", (data) => {
  doSomethingUseful(data);
});
```

### Динамический импорт

Этот пример показывает, как можно загрузить на страницу дополнительный модуль в зависимости от действий пользователя (в данном случае, по клику на кнопку), а затем использовать функции из загруженного модуля. Промисы - это не единственный способ использовать динамический импорт. Функция `import()` также может использоваться совместно с `await`.

```js
const main = document.querySelector("main");
for (const link of document.querySelectorAll("nav > a")) {
  link.addEventListener("click", (e) => {
    e.preventDefault();

    import("/modules/my-module.js")
      .then((module) => {
        module.loadPageInto(main);
      })
      .catch((err) => {
        main.textContent = err.message;
      });
  });
}
```

Спецификации
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-imports |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Смотрите также
--------------

* `export`
* Previewing ES6 Modules and more from ES2015, ES2016 and beyond
* ES6 in Depth: Modules, Hacks blog post by Jason Orendorff
* Axel Rauschmayer's book: "Exploring JS: Modules"


for - JavaScript

for
===

Введение
--------

Оператор **for** создаёт цикл, состоящий из трех необязательных выражений, заключенных в круглые скобки и разделенных точкой с запятой, за которыми следует инструкция (часто блок инструкций), которая должна выполняться в цикле.

Интерактивный пример
--------------------

Синтаксис
---------

```js
for ([инициализация]; [условие]; [финальное выражение])
  [инструкция]
```

* `инициализация` Необязательный
    + : Выражение (включая выражения присваивания) или объявление переменной, вычисляемое один раз перед началом цикла. Обычно используется для инициализации переменной счетчика. Это выражение может опционально объявлять новые переменные с ключевыми словами `var` или `let`. Переменные, объявленные с помощью `var`, не являются локальными для цикла, т.е. они находятся в той же области видимости, что и цикл `for`. Переменные, объявленные с помощью `let`, являются локальными для оператора и не доступны за пределами цикла.Результат выполнения этого выражения отбрасывается.
* `условие` Необязательный
    + : Выражение, которое будет выполнятся перед каждой итерацией цикла. Если выражение оценивается как true, инструкция выполняется. Если выражение оценивается как false, выполнение выходит из цикла и переходит к первой инструкции после конструкции `for`.Условие не является обязательным. Если его нет, условие всегда всегда оценивается как `true`.
* `финальное выражение` Необязательный
    + : Выражение, выполняющееся в конце итерации цикла. Происходит до следующего выполнения условия. Обычно используется для обновления или увеличения переменной счётчика.
* инструкция
    + : Инструкция, которая выполняется, когда условие цикла истинно. Чтоб выполнить множество инструкций в цикле, используйте блок инструкций (en-US) (`{ ... }`) для группировки этих инструкций. Чтобы не выполнять никакой инструкции в цикле, используйте пустую инструкцию (`;`).
Примеры
-------

### Использование `for`

Следующий цикл `for` начинается объявлением переменной `i` и задания ей значения `0`. Затем проверяет, что `i` меньше девяти, выполняет инструкцию внутри блока инструкций и инкрементирует (Инкремент (en-US)) `i` на каждой итерации.

```js
for (let i = 0; i < 9; i++) {
  console.log(i);
  // ещё какие-то инструкции
}
```

### Синтаксис блока инициализации

В блоке инициализации возможно как объявления переменных, так и более сложные выражения. Однако выражения не могут использовать оператор `in` без скобок, потому что это конфликтует с циклом `for...in`.

```js
for (let i = "start" in window ? window.start : 0; i < 9; i++) {
  console.log(i);
}
// SyntaxError: 'for-in' loop variable declaration may not have an initializer.
```

```js
// Все выражение инициализации переменной взято в скобки
for (let i = ("start" in window) ? window.start : 0; i < 9; i++) {
  console.log(i);
}

// Выражение `in` взято в скобки
for (let i = ("start" in window) ? window.start : 0; i < 9; i++) {
  console.log(i);
}
```

### Необязательные выражения в `for`

Все 3 выражения в цикле `for` не обязательны.

Например, в блоке инициализации не требуется определять переменные:

```js
let i = 0;
for (; i < 9; i++) {
  console.log(i);
  // ещё выражения
}
```

Как и блок инициализации, блок условия не обязателен. Если пропустите это выражение, вы должны быть уверены, что прервёте цикл где-то в теле, а не создадите бесконечный цикл.

```js
for (let i = 0; ; i++) {
  console.log(i);
  if (i > 3) break;
  // тут какой-то код
}
```

Вы можете пропустить все 3 блока. Снова убедитесь, что используете `break`, чтоб закончить цикл, а также изменить счётчик, так что условие для break было истинно в нужный момент.

```js
let i = 0;

for (;;) {
  if (i > 3) break;
  console.log(i);
  i++;
}
```

### Использование `for` без блока инструкций

Следующий цикл `for` вычисляет смещение позиции узла в секции `[финальное выражение]`, и, следовательно, не требует использования инструкции или `блока инструкций` (en-US) внутри цикла, вместо этого используется точка с запятой (пустая инструкция).

```js
function showOffsetPos(id) {
  let left = 0,
    top = 0;

  for (
    let itNode = document.getElementById(id); // инициализация
    itNode; // условие
    left += itNode.offsetLeft,
      top += itNode.offsetTop,
      itNode = itNode.offsetParent // финальное выражение
  ); // точка с запятой (пустая инструкция)

  console.log(
    `Смещение позиции элемента "${id}":
слева: ${left}px;
сверху: ${top}px;`,
  );
}

showOffsetPos("content");

// Выводит:
// Смещение позиции элемента "content":
// слева: 0px;
// сверху: 153px;"
```

**Примечание:** В этом случае, когда вы не используете условие внутри цикла, **точка с запятой ставится сразу после выражения цикла.**

Спецификации
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-for-statement |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Смотрите также
--------------

* пустая инструкция
* `break`
* `continue`
* `empty`
* `while`
* `do...while`
* `for...in`
* `for...of`


debugger - JavaScript

debugger
========

Выражение **debugger** открывает доступ к любому доступному в конкретном окружении отладочной функциональности, например к установке точек останова (т.н. брейкпоинтов). Если функциональность отладки в среде выполнения недоступен, данное выражение не будет иметь никакого эффекта.

Синтаксис
---------
```

debugger;
```

Примеры
-------

Следующий пример показывает код, содержащий выражение **debugger**. Это позволяет вызвать функциональность отладки (если таковой может быть использован) при вызове функции.

```js
function potentiallyBuggyCode() {
  debugger;
  // чтобы протестировать работу отладчика, поместите здесь код, заведомо содержащий ошибку
}
```

При вызове отладчика выполнение скрипта приостановится в том месте, где находится выражение **debugger**, что равноценно действию установленных в скрипте точек останова.

![Paused at a debugger statement.](/ru/docs/Web/JavaScript/Reference/Statements/debugger/screen_shot_2014-02-07_at_9.14.35_am.png)

Спецификация
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-debugger-statement |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Смотрите также
--------------

* Debugging JavaScript
* The Debugger in the Firefox Developer Tools


while - JavaScript

while
=====

Оператор **while** создаёт цикл, выполняющий заданную инструкцию, пока истинно проверяемое условие. Логическое значение условия вычисляется перед исполнением тела цикла.

Синтаксис
---------
```

while (условие) {
  инструкция
}
```

`условие`

Выражение, логическое значение которого проверяется каждый раз перед заходом в цикл. Если значение истинно, то исполняется `инструкция`. Когда значение становится ложным, выполняется код, следующий за циклом `while`.

`инструкция`

Инструкция, которая исполняется каждый раз, пока истинно условие. Чтобы выполнить несколько инструкций в цикле, используйте блочный оператор (`{ ... }`) для их группировки.

Примеры
-------

Следующий цикл `while` исполняется, пока `n` не превышает трёх.

```js
var n = 0;
var x = 0;

while (n < 3) {
  n++;
  x += n;
}
```

На каждой итерации цикла `n` увеличивается на единицу и прибавляется к `x`. Таким образом, `x` и `n` принимают следующие значения:

* После первого прохода: `n` = 1 и `x` = 1
* после второго прохода: `n` = 2 и `x` = 3
* После третьего прохода: `n` = 3 и `x` = 6

После окончания третьей итерации условие `n` < 3 больше не является истинным, поэтому цикл завершается.

Спецификации
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-while-statement |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Смотрите также
--------------

* `do...while`
* `for`


break - JavaScript

break
=====

**Оператор `break`** прерывает выполнение текущего цикла, оператора множественного выбора `switch` или блочного выражения с меткой. Выполнение кода продолжается с конструкции, следующей за прерванной.

Интерактивный пример
--------------------

Синтаксис
---------

```js
break [label];
```

`label` Необязательный

Идентификатор связанной метки. Если прерываемое выражение не цикл или `switch`, указание метки обязательно.

Описание
--------

С помощью оператора `break` можно прервать выполнение блочного выражения с меткой. В таком случае `break` должен находиться внутри блока кода с указанной меткой. Само блочное выражение может быть любым, а не только циклом.

Использование `break`, с меткой или без, невозможно внутри функции, которая вложена в прерываемые цикл, конструкцию `switch` или блочное выражение с меткой.

Примеры
-------

### break в цикле while

Следующая функция использует оператор `break` для выхода из цикла `while`, когда `i` станет равно 3, и возвращает значение 3 \* `x`.

```js
function testBreak(x) {
  var i = 0;

  while (i < 6) {
    if (i == 3) {
      break;
    }
    i += 1;
  }

  return i \* x;
}
```

### break в конструкции switch

В примере оператор `break` прервёт выполнение `switch` сразу после выполнения кода в совпавшем `case`.

```js
const food = "sushi";

switch (food) {
  case "sushi":
    console.log("Sushi is originally from Japan.");
    break;
  case "pizza":
    console.log("Pizza is originally from Italy.");
    break;
  default:
    console.log("I have never heard of that dish.");
    break;
}
```

### break в блочном выражении с указанной меткой

В примере используется оператор `break` с меткой. В таком случае `break` обязательно должен быть вложен в блок кода с той же меткой. Обратите внимание, что `inner_block` вложен в `outer_block`.

```js
outer\_block: {
  inner\_block: {
    console.log("1");
    break outer_block; // break прервёт выполнение кода как в inner\_block, так и в outer\_block
    console.log(":-("); // не будет выполнено
  }
  console.log("2"); // не будет выполнено
}
```

### break вне блочного выражения с указанной меткой

В примере также используется `break` с меткой, но код будет выполнен с ошибкой `SyntaxError`, потому что `break` находится в блоке с меткой `block_1`, а прерывается выполнение блока кода с меткой `block_2`. Ещё раз, в таком случае `break` обязательно должен быть вложен в блок кода с меткой, выполнение которого требуется прервать.

```js
block\_1: {
  console.log('1');
  break block_2; // SyntaxError: label not found
}

block\_2: {
  console.log('2');
}
```

### break внутри функций

Код в примерах также будет выполнен с ошибкой `SyntaxError`, потому что в обоих случаях `break` находится в теле функции, вложенной в прерываемый цикл или прерываемое блочное выражение с меткой.

```js
function testBreak(x) {
  var i = 0;

  while (i < 6) {
    if (i == 3) {
      (function() {
        break;
      })();
    }
    i += 1;
  }

return i \* x;
}

testBreak(1); // SyntaxError: Illegal break statement
```

```js
block\_1: {
  console.log('1');
  ( function() {
    break block_1; // SyntaxError: Undefined label 'block\_1'
  })();
}
```

Спецификации
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-break-statement |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Смотрите также
--------------

* `continue`
* label
* `switch`


Метка - JavaScript

Метка
=====

**Метки** используются вместе с операторами `break` и `continue`. Они выступают в роли идентификатора инструкции, на который можно сослаться.

Интерактивный пример
--------------------

Синтаксис
---------

```js
label:
  statement;
```

`label`

Идентификатор. Любое слово, кроме ключевых и зарезервированных в JavaScript.

`statement`

Инструкция. `break` может быть использован внутри любого блока инструкций с меткой, а с `continue` только внутри циклов.

Описание
--------

Вы можете использовать метки для обозначения циклов, чтобы затем при помощи `break` или `continue` выходить из цикла или продолжать его работу с новой итерации соответственно.

Обратите внимание, в JavaScript *отсутствует* оператор `goto`, вы можете использовать метки только с `break` или `continue`.

В строгом режиме использование слова "`let`" в качестве имени метки запрещено — вы получите ошибку `SyntaxError` (потому что `let` является ключевым словом в новых стандартах JavaScript).

Примеры
-------

### Использование метки с оператором continue в цикле

```js
let i, j;

loop1: for (i = 0; i < 3; i++) {
  //Первый цикл, обозначенный меткой "loop1"
  loop2: for (j = 0; j < 3; j++) {
    //Второй цикл, обозначенный меткой "loop2"
    if (i === 1 && j === 1) {
      continue loop1;
    }
    console.log("i = " + i + ", j = " + j);
  }
}

// Вывод:
// "i = 0, j = 0"
// "i = 0, j = 1"
// "i = 0, j = 2"
// "i = 1, j = 0"
// "i = 2, j = 0"
// "i = 2, j = 1"
// "i = 2, j = 2"
// Обратите внимание на пропуск "i = 1, j = 1" и "i = 1, j = 2"
```

### Другой пример использования метки с continue

В примере по массиву элементов и массиву тест-функций вычисляется количество элементов, которые проходят все тесты.

```js
let itemsPassed = 0;
let i, j;

top: for (i = 0; i < items.length; i++) {
  for (j = 0; j < tests.length; j++) {
    if (!tests[j].pass(items[i])) {
      continue top;
    }
  }

  itemsPassed++;
}
```

### Использование метки с оператором break в цикле

```js
let i, j;

loop1: for (i = 0; i < 3; i++) {
  //Первый цикл, обозначенный меткой "loop1"
  loop2: for (j = 0; j < 3; j++) {
    //Второй цикл, обозначенный меткой "loop2"
    if (i === 1 && j === 1) {
      break loop1;
    }
    console.log("i = " + i + ", j = " + j);
  }
}

// Вывод:
// "i = 0, j = 0"
// "i = 0, j = 1"
// "i = 0, j = 2"
// "i = 1, j = 0"
// Обратите внимание на разницу результатов в аналогичном примере с continue
```

### Другой пример использования метки с break

В примере по массиву элементов и массиву тест-функций определяется, все ли элементы проходят все тесты.

```js
let allPass = true;
let i, j;

top: for (i = 0; i < items.length; i++) {
  for (j = 0; j < tests.length; j++) {
    if (!tests[j].pass(items[i])) {
      allPass = false;
      break top;
    }
  }
}
```

### Использование метки для блока инструкций с break

Метки можно использовать для обычных блоков кода, но только с оператором `break`.

```js
foo: {
  console.log("привет");
  break foo;
  console.log("эта строка не будет исполнена");
}
console.log("мир");

// Вывод:
// "привет"
// "мир"
```

### Объявление функций с меткой

Начиная с ECMAScript 2015, объявление функции с меткой допускается только в обычном режиме для совместимости с этой нестандартной, но реализованной в некоторых браузерах, возможностью.

```js
L: function F() {}
```

Однако в строгом режиме такой код вызовет ошибку `SyntaxError`:

```js
"use strict";
L: function F() {}
// SyntaxError: functions cannot be labelled
```

Объявление функций-генераторов с меткой не допускается ни в обычном, ни в строгом режимах:

```js
L: function\* F() {}
// SyntaxError: generator functions cannot be labelled
```

Спецификации
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-labelled-statements |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Смотрите также
--------------

* `break`
* `continue`


class - JavaScript

class
=====

Baseline Widely available
-------------------------

This feature is well established and works across many devices and browser versions. It’s been available across browsers since March 2017.

* Learn more
* See full compatibility
* Report feedback
**Class declaration** создаёт новый класс с данным именем на основе прототипного наследования.

Можно так же определить класс, используя class expression. Но в отличие от class expression, class declaration не позволяет снова объявить уже существующий класс, это **приведёт к ошибке типа**.

Синтаксис
---------

```js
class name [extends] {
  // тело класса
}
```

Описание
--------

Как и class expression, тело class declaration будет исполняться в строгом режиме. Свойство конструктора является опциональным.

Class declaration не поднимается (в отличие от декларируемых функций).

Примеры
-------

### Простой class declaration

В следующем примере сначала определяется класс с именем Polygon, затем он наследуется для создания класса Square. Заметьте, что super(), используемый в конструкторе, может быть использован только в конструкторе и должен быть вызван до того, как будет использовано ключевое слово this.

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

class Square extends Polygon {
  constructor(length) {
    super(length, length);
    this.name = "Square";
  }
}
```

**Предупреждение:** ### Попытка объявить класс дваждыПереопределение класса с помощью class declaration вызовет ошибку типа. `js class Foo {}; class Foo {}; // Uncaught TypeError: Identifier 'Foo' has already been declared` Та же ошибка будет вызвана, если класс был определён перед использованием class declaration.

```js
var Foo = class {};
class Foo {} // Uncaught TypeError: Identifier 'Foo' has already been declared
```

Спецификации
------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-class-definitions |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Смотрите также
--------------

* `function` declaration
* `class` expression
* Classes