Логическое ИЛИ (

Логическое ИЛИ (||)
===================

Логический оператор ИЛИ (`||`) (дизъюнкция) для набора операндов истинен будет `true` только в случае, если один или несколько его операндов имеют значение `true`.

Обычно используется с `булевыми` (логическими) значениями. Тогда возвращается булевое значение. Однако фактически оператор `||` возвращает значение одного из операндов, поэтому если этот оператор используется с небулевыми значениями, он вернет небулевое значение.

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

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

```js
expr1 || expr2;
```

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

Если `expr1` может быть преобразовано в `true`, то вернётся `expr1`; в противном случае возвращается `expr2`.

Если значение может быть преобразовано в `true`, то оно рассматривается как истиноподобное (truthy). Если же значение может быть преобразовано в `false`, то оно называется ложноподобным (falsy).

Примеры выражений, которые могут быть преобразованы в `false`:

* `null`;
* `NaN`;
* `0`;
* пустая строка (`""`, `''`, ````);
* `undefined`.

 Несмотря на то, что оператор `||` может использоваться с операндами без логических значений, это всё равно булевый оператор, поскольку его возвращаемое значение всегда можно преобразовать в булевый примитив.
 Чтобы явно преобразовать возвращаемое значение этого оператора (или вообще любое выражение) в соответствующее значение булевого типа, используйте двойной `оператор НЕ` или конструктор `Boolean` (en-US).

### Сокращённое вычисление

Оператор логического ИЛИ вычисляется слева направо, делая возможным сокращённое вычисление выражения, согласно следующему правилу:

`(истинноподобное выражение) || следующее выражение` — вычисление останавливается на истинноподобном выражении;

 Сокращенное вычисление хорошо тем, что `следующее выражение` не будет **вычислено**, т.е. всё, связанное с ним, будет проигнорировано (например, если
 `следующее выражение` представляет собой вызов функции, то он никогда не произойдёт). Всё потому, что значение оператора известно уже после вычисления первого операнда. Посмотрите на пример:

```js
function A() {
  console.log("вызвана функция A");
  return false;
}
function B() {
  console.log("вызвана функция B");
  return true;
}

console.log(B() || A());
// В результате вызова функции B, в консоли будет выведено "вызвана функция B",
// а далее в консоли появится false (это результат оператора)
```

### Приоритет операторов

Следующие выражения могут показаться эквивалентными, но это не так, потому что оператор `&&` выполняется до оператора `||` (см. приоритет операторов).

```js
true || (false && false); // вернёт true, поскольку сначала вычисляется &&
(true || false) && false; // вернёт false, поскольку у группировки выше приоритет
```

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

### Использование оператора ИЛИ

В следующем коде показаны примеры использования оператора `||` (логическое ИЛИ).

```js
o1 = true || true; // t || t вернёт true
o2 = false || true; // f || t вернёт true
o3 = true || false; // t || f вернёт true
o4 = false || 3 == 4; // f || f вернёт false
o5 = "Cat" || "Dog"; // t || t вернёт "Cat"
o6 = false || "Cat"; // f || t вернёт "Cat"
o7 = "Cat" || false; // t || f вернёт "Cat"
o8 = "" || false; // f || f вернёт false
o9 = false || ""; // f || f вернёт ""
o10 = false || varObject; // f || object вернёт varObject
```

**Примечание:** Если вы используете этот оператор, чтобы задать значение по умолчанию для некоторой переменной, имейте в виду, что любое *ложноподобное* будет проигнорировано. Если вам нужно исключить только `null` или `undefined`, попробуйте воспользоваться оператором нулевого слияния.

### Правила конвертации для булевых значений

#### Конвертация И в ИЛИ

Следующая операция с **булевыми значениями**:

```js
bCondition1 && bCondition2;
```

всегда эквивалентна:

```js
!(!bCondition1 || !bCondition2);
```

#### Конвертация ИЛИ в И

Следующая операция с **булевыми значениями**:

```js
bCondition1 || bCondition2;
```

всегда эквивалентна:

```js
!(!bCondition1 && !bCondition2);
```

### Удаление вложенных круглых скобок

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

Следующая составная операция с **булевыми значениями**:

```js
bCondition1 && (bCondition2 || bCondition3);
```

всегда эквивалентна:

```js
!(!bCondition1 || (!bCondition2 && !bCondition3));
```

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

| Specification |
| --- |
| ECMAScript Language Specification # prod-LogicalORExpression |

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

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

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

* Оператор нулевого слияния (`??`)
* `Boolean`
* Truthy
* Falsy


yield* - JavaScript

yield\*
=======

\*\*Выражение `yield*` \*\*используется для того, чтобы "передать управление" функцией-генератором другому `генератору` или итерируемому объекту.

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

 yield* [[expression]];
```

`expression`

Итерируемый объект

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

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

Значение выражения `yield*` само по себе равно последнему значению итерируемого объекта (т.е., того когда `done` равно true).

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

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

В следующем примере, значения полученные из `g1()` возвращаются из `g2` вызовами `next`, как будто бы она вычислила их сама.

```js
function\* g1() {
  yield 2;
  yield 3;
  yield 4;
}

function\* g2() {
  yield 1;
  yield\* g1();
  yield 5;
}

var iterator = g2();

console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: 4, done: false }
console.log(iterator.next()); // { value: 5, done: false }
console.log(iterator.next()); // { value: undefined, done: true }
```

### Другие итерируемые объекты

Помимо объектов генераторов, `yield*` может перебирать другие виды итерируемых объектов, т.е. массивы, строки, объекты аргументов и др.

```js
function\* g3() {
  yield\* [1, 2];
  yield\* "34";
  yield\* Array.from(arguments);
  // Определение этого итератора ниже
  yield\* new PowesOfTwo(4);
}

var iterator = g3(5, 6);

// Значения из массива
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
// Из строки
console.log(iterator.next()); // { value: "3", done: false }
console.log(iterator.next()); // { value: "4", done: false }
// Из аргументов
console.log(iterator.next()); // { value: 5, done: false }
console.log(iterator.next()); // { value: 6, done: false }
// Из специального итератора
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 4, done: false }

console.log(iterator.next()); // { value: undefined, done: true }

// Итератор, который возвращает все степени двойки
// до maximum включительно
class PowersOfTwo {
  constructor(maximum) {
    this.maximum = maximum;
    this.value = 1;
  }
  [Symbol.iterator]() {
    const self = this;
    return {
      next() {
        if (self.value > self.maximum) return { done: true };

        const value = self.value;
        self.value \*= 2;
        return { done: false, value };
      },
    };
  }
}
```

### Собственное значение выражения `yield*`

`yield*` - это выражение, а не оператор, поэтому оно имеет значение, равное последнему значению итератора

```js
function\* g4() {
  yield\* [1, 2, 3];
  return "foo";
}

var result;

function\* g5() {
  result = yield\* g4();
}

var iterator = g5();

console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true },
// g4() в этой точке вернёт { value: "foo", done: true }

console.log(result); // "foo"
```

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

| Specification |
| --- |
| ECMAScript Language Specification # sec-generator-function-definitions-runtime-semantics-evaluation |

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

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

Специфичные для Firefox примечания
----------------------------------

* Начиная с Gecko 33, разбор выражений yield было приведено к соответствию с последними спецификациями ES6 (Firefox bug 981599):
    + Реализована корректная обработка разрыва строки. Разрыва строки между "yield" и "\*" быть не может. Такой код вызовет `SyntaxError`:
     js
    ```js
    function\* foo() {
      yield
      \*[];
    }

    ```
See also
--------

* The Iterator protocol
* `function*`
* `function* expression`
* `yield`


import.meta - JavaScript

import.meta
===========

`Объект import.meta` это мета-свойство, указывающее мета-данные JavaScript модуля в зависимости от контекста. Он содержит информацию о модуле, например, URL модуля.

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

import.meta
```

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

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

Объект `import.meta` создан по реализации ECMAScript с прототипом объекта `null`. Этот объект расширяем, и его свойства являются записываемыми, настраиваемыми и перечисляемыми.

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

Допустим, есть модуль `my-module.js`

```html
<script type="module" src="my-module.js"></script>
```

вы можете получить доступ к мета-информации об этом модуле, используя объект `import.meta`.

```js
console.log(import.meta); // { url: "file:///home/user/my-module.js" }
```

Это возвращает объект со свойством `url` показывающее базовый URL этого модуля. Это может быть либо URL с которого скрипт был получен (для внешних скриптов), либо базовый URL содержащего его документа (для внутренних скриптов).

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

| Specification |
| --- |
| ECMAScript Language Specification # prod-ImportMeta |
| HTML Standard # hostgetimportmetaproperties |

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

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

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

* `import`
* `export`


new.target - JavaScript

new.target
==========

Свойство **`new.target`** позволяет определить была ли функция или конструктор вызваны с помощью оператора new. В конструкторах и функциях инстанциированных с помощью оператора new, `new.target` возвращает ссылку на конструктор или функцию. При обычном вызове функции `new.target` имеет значение `undefined`.Синтаксис
---------
```

new.target
```

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

Синтаксис `new.target` состоит из ключевого слова `new`, точки, и свойства `target`. Обычно `new` служит контекстом для доступа к свойству, но здесь `new` не совсем объект. Однако при вызове конструктора, `new.target` ссылается на конструктор вызванный с помощью `new` и таким образом `new` становится виртуальным контекстом.

Свойство `new.target` это мета свойство которое доступно во всех функциях. В стрелочных функция, `new.target` ссылается на `new.target` внешней функции.

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

### new.target в вызове функции

При обычном вызове функции (в противоположность вызову в качестве конструктора), `new.target` имеет значение `undefined`. Это позволяет определить была ли вызвана функция как конструктор через new или нет.

```js
function Foo() {
  if (!new.target) throw "Foo() must be called with new";
  console.log("Foo instantiated with new");
}

new Foo(); // выведет "Foo instantiated with new"
Foo(); // ошибка "Foo() must be called with new"
```

### new.target в конструкторе

В конструкторе класса, `new.target` ссылается на конструктор, который был непосредственно вызван `new`. Это верно и для случая, когда `new.target` находится в конструкторе родительского класса, а тот в свою очередь вызывается из конструктора дочернего класса.

```js
class A {
  constructor() {
    console.log(new.target.name);
  }
}

class B extends A {
  constructor() {
    super();
  }
}

var a = new A(); // вернёт "A"
var b = new B(); // вернёт "B"
```

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

| Specification |
| --- |
| ECMAScript Language Specification # sec-built-in-function-objects |

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

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

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

* Functions
* Classes
* `new`
* `this`


Присваивание (=) - JavaScript

Присваивание (=)
================

Простой оператор присваивания (`=`) используется для присваивания значения переменной. Операция присваивания вычисляется в присваиваемую величину. Присваивание по цепочке (*chaining*) используется для назначения нескольким переменным одинакового значения.

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

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

Оператор: x = y
```

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

### Простое и цепное присваивание

```js
// Предположим следующие переменные и их значения
// x = 5
// y = 10
// z = 25

x = y; // x будет присвоено значение 10
x = y = z; // x, y и z будут равны 25
```

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

| Specification |
| --- |
| ECMAScript Language Specification # sec-assignment-operators |

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

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

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

* Assignment operators in the JS guide


null - JavaScript

null
====

Значение `null` представляет отсутствие какого-либо объектного значения. В JavaScript, `null` является примитивом, и в контексте логических операций, рассматривается как ложное (falsy).

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

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

null
```

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

Значение `null` записывается литералом `null`. Оно является самостоятельным, а не свойством глобального объекта (как `undefined`). В API, `null` часто присутствует в местах где ожидается объект, но подходящего объекта нет.

```js
// переменная foo не существует - она не была определена и никогда не инициализировалась:
> foo
'ReferenceError: foo is not defined'

// переменная foo существует, но она не имеет ни типа, ни значения:
> var foo = null; foo
'null'
```

### Отличия между `null` и `undefined`

`null` является определённым значением отсутствия объекта, тогда как `undefined` обозначает неопределённость. Например:

```js
var element;
// значение переменной element до её инициализации не определённо: undefined

element = document.getElementById("not-exists");
// здесь при попытке получения несуществующего элемента, метод getElementById возвращает null
// переменная element теперь инициализирована значением null, её значение определено
```

При проверке на `null` или `undefined`, помните о различии между операторами равенства (==) и идентичности (===): с первым, выполняется преобразование типов.

```js
typeof null; // object (не "null" из соображений обратной совместимости)
typeof undefined; // undefined
null === undefined; // false
null == undefined; // true
```

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

| Specification |
| --- |
| ECMAScript Language Specification # sec-null-value |

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

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

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

* `undefined`
* `NaN`


this - JavaScript

this
====

Поведение ключевого слова `this` в JavaScript несколько отличается по сравнению с остальными языками. Имеются также различия при использовании `this` в строгом и нестрогом режиме.

В большинстве случаев значение `this` определяется тем, каким образом вызвана функция. Значение `this` не может быть установлено путём присваивания во время исполнения кода и может иметь разное значение при каждом вызове функции. В ES5 представлен метод `bind()`, который используется для `привязки значения ключевого слова this независимо от того, как вызвана функция`. Также в ES2015 представлены `стрелочные функции`, которые не создают собственные привязки к `this` (они сохраняют значение `this` лексического окружения, в котором были созданы).

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

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

this
```

### Значение

Свойство контекста выполнения кода (global, function или eval), которое в нестрогом режиме всегда является ссылкой на объект, а в строгом режиме может иметь любое значение.

Global контекст
---------------

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

```js
// В браузерах, объект window также является объектом global:
console.log(this === window); // true

a = 37;
console.log(window.a); // 37

this.b = "MDN";
console.log(window.b); // "MDN"
console.log(b); // "MDN"
```

**Примечание:** вы всегда можете легко получить объект global, используя глобальное свойство `globalThis`, независимо от текущего контекста, в котором выполняется ваш код.

Function контекст
-----------------

В пределах функции значение `this` зависит от того, каким образом вызвана функция.

### Простой вызов

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

```js
function f1() {
  return this;
}

// В браузере:
f1() === window; // window - глобальный объект в браузере

// В Node:
f1() === global; // global - глобальный объект в Node
```

В строгом режиме, если значение `this` не установлено в контексте выполнения, оно остаётся `undefined`, как показано в следующем примере:

```js
function f2() {
  "use strict"; // см. strict mode
  return this;
}

f2() === undefined; // true
```

**Примечание:** Во втором примере `this` должно иметь значение ``undefined``, потому что функция `f2` была вызвана напрямую, а не как метод или свойство объекта (например, `window.f2()`). Реализация этой особенности не поддерживалась в некоторых браузерах, когда они впервые начали поддерживать `строгий режим`. В результате они некорректно возвращали объект `window`.

Для того, чтобы при вызове функции установить `this` в определённое значение, используйте `call()` или `apply()`, как в следующих примерах.

### Пример 1

```js
// В качестве первого аргумента методов call или apply может быть передан объект,
// на который будет указывать this.
var obj = { a: "Custom" };

// Это свойство принадлежит глобальному объекту
var a = "Global";

function whatsThis() {
  return this.a; //значение this зависит от контекста вызова функции
}

whatsThis(); // 'Global'
whatsThis.call(obj); // 'Custom'
whatsThis.apply(obj); // 'Custom'
```

### Пример 2

```js
function add(c, d) {
  return this.a + this.b + c + d;
}

var o = { a: 1, b: 3 };

// Первый параметр - это объект для использования в качестве
// 'this', последующие параметры передаются как
// аргументы функции call
add.call(o, 5, 7); // 16

// Первый параметр - это объект для использования в качестве
// 'this', второй - массив, чьи члены используются
// в качестве аргументов функции call
add.apply(o, [10, 20]); // 34
```

Обратите внимание, что в нестрогом режиме, если значение, переданное в `call` или `apply как` `this`, не является объектом, будет сделана попытка преобразовать его в объект с помощью внутренней операции `ToObject`. Таким образом, если переданное значение является примитивом, таким как `7` или `'foo'`, оно будет преобразовано в `Object` с использованием связанного конструктора, так что примитивное число `7` будет преобразовано в объект так, как будто с помощью `new Number(7)`, а строка `'foo'` - как будто с помощью `new String('foo')`, например

```js
function bar() {
  console.log(Object.prototype.toString.call(this));
}

bar.call(7); // [object Number]
bar.call("foo"); // [object String]
```

### Метод `bind`

ECMAScript 5 представил `Function.prototype.bind()`. Вызов `f.bind(someObject)` создаёт новую функцию с тем же телом и областью действия, что и `f`, но там, где в исходной функции используется `this`, в новой функции оно постоянно будет связано с первым аргументом `bind`, независимо от того, как функция используется.

```js
function f() {
  return this.a;
}

var g = f.bind({ a: "azerty" });
console.log(g()); // azerty

var h = g.bind({ a: "yoo" }); // bind only works once!
console.log(h()); // azerty

var o = { a: 37, f: f, g: g, h: h };
console.log(o.a, o.f(), o.g(), o.h()); // 37,37, azerty, azerty
```

### Стрелочные функции

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

```js
var globalObject = this;
var foo = () => this;
console.log(foo() === globalObject); // true
```

**Примечание:** Note: если аргумент this передаётся в call, bind или apply при вызове стрелочной функции, он будет проигнорирован. Вы всё ещё можете добавить аргументы к вызову, но первый аргумент (thisArg) должен быть установлен в null.

Неважно, как стрелочная функция `foo()` будет вызвана, её значение this будет указывать на глобальный объект. `this` будет сохранять своё значение, даже если функция `foo()` будет вызвана как метод объекта (что в обычных функциях связывает `this` с объектом вызова) или с использованием методов `call`, `apply` или `bind`:

```js
// Вызов функции как метода объекта
var obj = { foo: foo };
console.log(obj.foo() === globalObject); // true

// Попытка установить this с помощью call
console.log(foo.call(obj) === globalObject); // true

// Попытка установить this с помощью bind
foo = foo.bind(obj);
console.log(foo() === globalObject); // true
```

Несмотря ни на что, `this` стрелочной функции `foo()` имеет то же значение, что и при создании функции (глобальный объект в примере выше). То же самое касается стрелочных функций, созданных внутри других функций: их `this` будет привязан к окружению.

```js
// Создаём объект obj, содержащий метод bar, который возвращает функцию,
// которая возвращает свой this. Возвращаемая функция создана
// как стрелочная функция, таким образом её this постоянно замкнут
// на this функции, в которой она создана. Значение bar может быть установлено
// в вызове, который, в свою очередь, устанавливает значение возвращаемой функции.
var obj = {
  bar: function () {
    var x = () => this;
    return x;
  },
};

// Вызываем bar как метод объекта obj, устанавливая его this на obj
// Присваиваем ссылку возвращаемой функции переменной fn
var fn = obj.bar();

// Вызываем fn без установки this, что в обычных функциях указывало бы
// на глобальный объект или undefined в строгом режиме.
console.log(fn() === obj); // true

// Но будьте осторожны, если вы ссылаетесь на метод obj, не вызывая его
var fn2 = obj.bar;
// Вызов this стрелочной функции изнутри метода bar вернёт теперь window,
// потому что он следует за this из fn2.
console.log(fn2()() == window); // true
```

В примере выше, функция (назовём её анонимной функцией A), присвоенная методу `obj.bar`, возвращает другую функцию (назовём её анонимной функцией B) которая создана как стрелочная функция. В результате, `this функции B при вызове замкнут на` `this,` принадлежащий `obj.bar` (функции A). `this` функции B всегда будет иметь то значение, которое он получил при создании. В примере выше, `this функции B` указывает на `this функции A,которым является` obj, таким образом this будет равен `obj` даже тогда, когда будет вызван методом, который в нормальных условиях устанавливал бы значение this равным `undefined` или глобальному объекту (или любым другим методом, как в предыдущем примере в глобальном контексте выполнения).

### В методе объекта

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

В следующем примере, когда вызвано свойство `o.f()` , внутри функции `this` привязано к объекту `o.`

```js
var o = {
  prop: 37,
  f: function () {
    return this.prop;
  },
};

console.log(o.f()); // logs 37
```

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

```js
var o = { prop: 37 };

function independent() {
  return this.prop;
}

o.f = independent;

console.log(o.f()); // logs 37
```

Эти примеры показывают, что имеет значение только то, что функция была вызвана из свойства `f` объекта `o`.

Аналогично, привязывание `this` обуславливается наличием ближайшей ссылки на объект или свойство. В следующем примере, когда мы вызываем функцию, мы обращаемся к ней как к методу `g` объекта `o.b`. На этот раз во время выполнения, `this`, что находится внутри функции, будет ссылаться на `o.b`. Тот факт, что объект является членом объекта `o`, не имеет значения; важна только ближайшая ссылка.

```js
o.b = { g: independent, prop: 42 };
console.log(o.b.g()); // logs 42
```

#### `this` в цепочке object's prototype

Это же представление справедливо и для методов, определённых где-либо в цепочке object's prototype. Если метод находится в цепочке прототипов, то `this` ссылается на объект, на котором был вызван метод, т.е. так, словно метод является методом самого объекта, а не прототипа.

```js
var o = {
  f: function () {
    return this.a + this.b;
  },
};
var p = Object.create(o);
p.a = 1;
p.b = 4;

console.log(p.f()); // 5
```

В этом примере объект, который присвоен переменной `p`, не имеет собственного свойства `f`, а наследует это свойство от своего прототипа. Однако, совершенно неважно, что поиск свойства f в конце концов обнаружит его на объекте `o`. Поскольку поиск начался с `p.f`, то и свойство `this` внутри функции `f` будет ссылаться на объект `p`. Таким образом, если `f` вызывается как метод `p`, то и `this` относится к `p`. Это полезная особенность прототипного наследования JS.

#### `this` с геттерами/сеттерами

Все те же утверждения справедливы, если функция вызывается из геттера или сеттера. Для функции, которая используется как геттер или сеттер `this` привязан к объекту, свойство которого необходимо извлечь через геттер/сеттер.

```js
function modulus() {
  return Math.sqrt(this.re \* this.re + this.im \* this.im);
}

var o = {
  re: 1,
  im: -1,
  get phase() {
    return Math.atan2(this.im, this.re);
  },
};

Object.defineProperty(o, "modulus", {
  get: modulus,
  enumerable: true,
  configurable: true,
});

console.log(o.phase, o.modulus); // logs -0.78 1.4142
```

### В конструкторе

Когда функция используется как конструктор (с ключевым словом `new` ), `this` связано с создаваемым новым объектом.

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

```js
/\*
 \* Конструктор работает таким образом:
 \*
 \* function MyConstructor(){
 \* // фактический код, составляющий тело функции.
 \* // создание свойств с |this| по
 \* // желанию, определяя их значения; например,
 \* this.fum = "nom";
 \* // и т.д.
 \*
 \* // Если функция возвращает выражение,
 \* // возвращающее объект, этот объект будет
 \* // результатом выражения |new|. В обратном случае,
 \* // результат выражения - объект,
 \* // в данный момент привязанный к |this|
 \* // (т.е. наиболее часто встречающийся случай).
 \* }
 \*/

function C() {
  this.a = 37;
}

var o = new C();
console.log(o.a); // logs 37

function C2() {
  this.a = 37;
  return { a: 38 };
}

o = new C2();
console.log(o.a); // logs 38
```

В последнем примере (`C2`), из-за того, что конструктор вернул объект, новый объект, к которому было привязано `this`, был просто отброшен. (Это фактически делает выражение "`this.a = 37;`" "мёртвым" кодом. Он не является буквально нерабочим, так как он выполняется, но он может быть изъят без каких-либо внешних эффектов.)

### `call` и `apply`

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

```js
function add(c, d) {
  return this.a + this.b + c + d;
}

var o = { a: 1, b: 3 };

// Первый параметр - это объект, который следует использовать как
// 'this', последующие параметры передаются
// как аргументы при вызове функции
add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16

// Первый параметр - объект, который следует использовать как
// 'this', второй параметр - массив,
// элементы которого используются как аргументы при вызове функции
add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34
```

Необходимо отметить, что если методам `call` и `apply` передаётся значение с `this`, которое не является при этом объектом, будет предпринята попытка конвертировать значение в объект, используя внутреннюю операцию `ToObject`. Если переданное значение является примитивным типом, например `7` или `'foo'`, оно будет преобразовано в объект с использованием родственного конструктора, так примитив `7` преобразовывается в объект через `new Number(7),` а строка `'foo'` в объект через `new String('foo'),` и т.д.

```js
function bar() {
  console.log(Object.prototype.toString.call(this));
}

bar.call(7); // [object Number]
```

### Как обработчик событий DOM

Когда функция используется как обработчик событий, `this` присваивается элементу с которого начинается событие (некоторые браузеры не следуют этому соглашению для обработчиков, добавленных динамически с помощью всех методов, кроме `addEventListener`).

```js
// Когда вызывается как обработчик, связанный элемент становится синим
function bluify(e) {
  // Всегда true
  console.log(this === e.currentTarget);
  // true, когда currentTarget и target один объект
  console.log(this === e.target);
  this.style.backgroundColor = "#A5D9F3";
}

// Получить список каждого элемента в документе
var elements = document.getElementsByTagName("\*");

// Добавить bluify как обработчика кликов, чтобы при
// нажатии на элемент он становился синим
for (var i = 0; i < elements.length; i++) {
  elements[i].addEventListener("click", bluify, false);
}
```

### В инлайновом обработчике событий

Когда код вызван из инлайнового обработчика, `this` указывает на DOM-элемент, в котором расположен код события:

```js
<button onclick="alert(this.tagName.toLowerCase());">Показать this</button>
```

Код выше выведет '`button`'. Следует отметить, что `this` будет указывать на DOM-элемент только во внешних (не вложенных) функциях:

```js
<button onclick="alert((function() {return this;} ()));">
  Показать вложенный this
</button>
```

В этом случае `this` вложенной функции не будет установлен, так что будет возвращён global/window объект.

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

| Specification |
| --- |
| ECMAScript Language Specification # sec-this-keyword |

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

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

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

* Строгий режим
* All this, статья о `this` в разном контексте
* Краткое объяснение ключевого слова 'this' в JavaScript


Оператор нулевого слияния (??) - JavaScript

Оператор нулевого слияния (??)
==============================

**Оператор нулевого слияния (`??`)** — это логический оператор, возвращающий значение правого операнда, если значение левого операнда содержит `null` или `undefined`, в противном случае возвращается значение левого операнда.

Этот оператор можно рассматривать как частный случай логического оператора ИЛИ
(`||`), который возвращает правый операнд, если в левом операнде хранится *любое* ложноподобное значение, а не только `null` или `undefined`. Другими словами, если вы используете оператор `||` для присваивания значения по умолчанию другой переменной `foo`, вы можете столкнуться с неожиданным поведением, если считаете некоторые ложноподобные значения пригодными для использования (например, `''` или `0`). Ниже вы увидите примеры.

Оператор нулевого слияния вместе с `||` находится на четвёртом по приоритетности месте, непосредственно перед ним следует условный (тернарный) оператор.

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

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

```js
leftExpr ?? rightExpr;
```

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

### Использование оператора нулевого слияния

 В этом примере показано как устанавливать значения по умолчанию, отличные от
 `null` или `undefined`.

```js
const nullValue = null;
const emptyText = ""; // ложноподобное
const someNumber = 42;

const valA = nullValue ?? "значение для A";
const valB = emptyText ?? "значение для B";
const valC = someNumber ?? 0;

console.log(valA); // "значение для A"
console.log(valB); // "" (поскольку пустая строка не приравнивается к null или undefined)
console.log(valC); // 42
```

### Присваивание переменной значения по умолчанию

Ранее, когда нужно было присвоить переменной значение по умолчанию, часто использовался оператор ИЛИ (`||`):

```js
let foo;

// foo ещё не было присвоено значение, поэтому оно undefined
let someDummyText = foo || "Hello!";
```

Однако поскольку `||` является логическим оператором, левый операнд был принудительно приведен к булеву значению, игнорируя любое *ложноподобное* значение (`0`, `''`, `NaN`, `null`, `undefined`). Это может привести к некорректной работе кода, если нужно учитывать такие значения, как `0`, `''`, или `NaN`.

```js
let count = 0;
let text = "";

let qty = count || 42;
let message = text || "hi!";
console.log(qty); // 42, но не 0
console.log(message); // "hi!", но не ""
```

Оператор нулевого слияния предотвращает попадание в такую ловушку, возвращая второй операнд, только если первый равен `null` или `undefined` (и не любым другим ложноподобным значением):

```js
let myText = ""; // Пустая строка (ложноподобное значение)

let notFalsyText = myText || "Привет, мир";
console.log(notFalsyText); // Привет, мир

let preservingFalsy = myText ?? "Привет, сосед";
console.log(preservingFalsy); // '' (т.к. myText не ни undefined, ни null)
```

### Сокращённое вычисление

Так же как при использовании операторов логического И и ИЛИ, правое выражение не вычисляется, если значение в левом выражении не равняется `null` или `undefined`

```js
function A() {
  console.log("вызвана A");
  return undefined;
}
function B() {
  console.log("вызвана B");
  return false;
}
function C() {
  console.log("вызвана C");
  return "foo";
}

console.log(A() ?? C());
// в консоли будет будет выведено "вызвана A", после "вызвана C", и затем "foo",
// т.к. A() возвращает undefined, поэтому оба выражения были вычислены

console.log(B() ?? C());
// в консоли будет выведено "вызвана B", затем "false",
// так B() возвращает false (не null или undefined), то
// правое выражение не вычисляется
```

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

Не получится использовать оператор И (`&&`) и ИЛИ (`||`) вместе с оператором `??` в одном выражении. В таких случаях будет вызвана ошибка `SyntaxError`.

```js
null || undefined ?? "foo"; // вызывает SyntaxError
true || undefined ?? "foo"; // вызывает SyntaxError
```

Но если явно указать приоритет, создав подвыражение через круглые скобки, то всё заработает:

```js
(null || undefined) ?? "foo"; // вернёт "foo"
```

### Использование совместно с оператором опциональной последовательности (`?.`)

Оператор нулевого слияния учитывает значения `undefined` и `null`, по аналогии как и оператор опциональной последовательности (`?.`)(/ru/docs/Web/JavaScript/Reference/Operators/Optional\_chaining), который позволяет избежать ошибок при обращении к свойству объекта, которое может быть `null` или `undefined`.

```js
let foo = { someFooProp: "привет" };

console.log(foo.someFooProp?.toUpperCase() ?? "нет значения"); // "ПРИВЕТ"
console.log(foo.someBarProp?.toUpperCase() ?? "нет значения"); // "нет значения"
```

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

| Specification |
| --- |
| ECMAScript Language Specification # prod-CoalesceExpression |

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

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

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

* Оператор опциональной последовательности
* Оператор логического ИЛИ (`||`)
* Параметры по умолчанию функций


Логическое НЕ (!) - JavaScript

Логическое НЕ (!)
=================

Логический оператор НЕ (`!`) (логическое отрицание) меняет логическое значение операнда с истины в ложь и наоборот. Обычно он используется с `булевыми` (логическими) значениями. При использовании с любыми другими значениями, если операнд может быть преобразован в `true`, то вернёт `false`; в противном случае он возвращается `true`.

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

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

```js
!expr;
```

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

Возвращает `false`, если операнд может быть преобразован в `true`; в противном случае возвращается `true`.

Если значение может быть преобразовано в `true`, то оно рассматривается как истинноподобное (truthy). Если же значение может быть преобразовано в `false`, то оно называется ложноподобным (falsy).

Примеры выражений, которые могут быть преобразованы в `false`:

* `null`;
* `NaN`;
* `0`;
* пустая строка (`""`, `''`, ````);
* `undefined`.

Несмотря на то, что оператор `!` может использоваться с операндами, значения которых не относится к типу Boolean, это всё равно булевый оператор, поскольку его возвращаемое значение всегда можно преобразовать в булевый примитив. Чтобы явно преобразовать возвращаемое значение этого оператора (или вообще любое выражение) в соответствующее значение булевого типа, используйте двойной оператор НЕ (en-US) или конструктор `Boolean` (en-US).

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

### Использование логического НЕ

В следующем коде показаны примеры использования оператора `!` (логическое НЕ).

```js
n1 = !true; // !t вернёт false
n2 = !false; // !f вернёт true
n3 = !""; // !f вернёт true
n4 = !"Cat"; // !t вернёт false
```

### Двойное НЕ (`!!`)

 Можно один за другим использовать пару операторов НЕ, чтобы явным образом принудительно преобразовать любое значение в соответствующий булевый примитив.
 Преобразование основано на "истинноподобности" или "ложноподобности" значения (см. truthy и falsy)).

Точно такое же преобразование может быть выполнено с помощью функции `Boolean` (en-US).

```js
n1 = !!true; // !!truthy вернёт true
n2 = !!{}; // !!truthy вернёт true: любой объект - истинноподобный...
n3 = !!new Boolean(false); // ...даже Boolean-объект со значением false из вызова .valueOf()!
n4 = !!false; // !!falsy вернёт false
n5 = !!""; // !!falsy вернёт false
n6 = !!Boolean(false); // !!falsy вернёт false
```

### Конвертация операторов НЕ

Следующая операция с **булевыми значениями**:

```js
!!bCondition;
```

всегда эквивалентна:

```js
bCondition;
```

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

| Specification |
| --- |
| ECMAScript Language Specification # sec-logical-not-operator |

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

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

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

* `Boolean`
* Truthy
* Falsy


class expression - JavaScript

class expression
================

**Class expression** это способ определения класса в ECMAScript 2015 (ES6). Схожий с function expressions, class expressions может быть именованным либо не иметь имени. Если он именованный, то его имя доступно только внутри класса. JavaScript классы используют прототипно-ориентирование наследование.

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

var MyClass = class [className] [extends] {
  // тело класса
};
```

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

Class expression имеет схожий синтаксис с class declaration (statement). Однако в class expression можно опустить имя класса ("binding identifier"), что не допустимо с class declaration. Также class expression позволяет повторно объявить уже существующий класс и это **не приведёт к ошибке типа**, как при использовании class declaration. Свойство конструктора является опциональным. Результатом вызова оператора `typeof` на классах, сгенерированных при помощи class expression, всегда будет "function".

Так же, как и при использовании class declaration, тело класса у class expression будет исполняться в строгом режиме.

```js
"use strict";
var Foo = class {}; // свойство конструктора опционально
var Foo = class {}; // повторное объявление разрешено

typeof Foo; // возвращает "function"
typeof class {}; // возвращает "function"

Foo instanceof Object; // true
Foo instanceof Function; // true
class Foo {} // Throws TypeError, doesn't allow re-declaration
```

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

### Простой class expression

Простой анонимный class expression, на который можно сослаться с помощью переменной "Foo".

```js
var Foo = class {
  constructor() {}
  bar() {
    return "Hello World!";
  }
};

var instance = new Foo();
instance.bar(); // "Hello World!"
Foo.name; // "Foo"
```

### Именованный class expression

Если вы хотите сослаться на конкретный класс внутри тела класса, вы можете создать именованный class expression. Это имя будет доступно только внутри области видимости самого class expression.

```js
var Foo = class NamedFoo {
  constructor() {}
  whoIsThere() {
    return NamedFoo.name;
  }
};
var bar = new Foo();
bar.whoIsThere(); // "NamedFoo"
NamedFoo.name; // ReferenceError: NamedFoo is not defined
Foo.name; // "NamedFoo"
```

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

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

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

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

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

* `function` expression
* `class` statement
* Classes


Функциональное выражение - JavaScript

Функциональное выражение
========================

Ключевое слово **`function`** может использоваться для определения функции внутри выражения.

Вы можете также определять функции используя конструктор `Function` и `объявление функции`.

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

var myFunction = function [name]([param1[, param2[, ..., paramN]]]) {
   statements
};
```

С версии ES2015 можно также использовать стрелочные функции.

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

`name`

Имя функции. Может быть опущено, в таком случае функция является *анонимной*. Имя функции является локальным для её тела.

`paramN`

Имя аргумента, передаваемого в функцию.

`statements`

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

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

Функциональное выражение и объявление функции очень похожи и имеют почти одинаковый синтаксис. Главным отличием между ними является *имя функции,* которое в случае функциональных выражений может быть опущено для создания *анонимных* функций. Функциональное выражение может быть использовано для создания самовызывающейся функции IIFE (Immediately Invoked Function Expression), которая исполняется сразу же после того, как она была определена. Более подробная информация изложена в разделе о функциях.

### Поднятие функциональных выражений

Функциональные выражения в JavaScript не поднимаются (hoisting), в отличие от `объявленных функций`. Вы не можете использовать функциональные выражения прежде, чем вы их определили.

```js
console.log(notHoisted); // undefined
//Хотя объявленная переменная и поднимается, определение переменной происходит позже
notHoisted(); // TypeError: notHoisted is not a function

var notHoisted = function () {
  console.log("bar");
};
```

### Именованное функциональное выражение

Если вы хотите сослаться на текущую функцию внутри тела этой функции, вам необходимо создать именованное функциональное выражение. Данное имя будет локальным только для тела функции (её области видимости). Кроме того, это позволяет избежать использования нестандартного свойства `arguments.callee`.

```js
var math = {
  factit: function factorial(n) {
    console.log(n);
    if (n <= 1) {
      return 1;
    }
    return n \* factorial(n - 1);
  },
};

math.factit(3); //3;2;1;
```

Переменная, которой присвоено функциональное выражение, будет иметь свойство `name`, содержащее имя функции. Оно не изменится при переприсваивании другой переменной. Для анонимной функции, значением свойства `name` будет имя переменной (неявное имя). Если же имя задано, то будет использовано имя функции (явное имя). Это же касается стрелочных функций (в их случае там будет записано имя переменной, т.к. они всегда анонимные).

```js
var foo = function () {};
foo.name; // "foo"

var foo2 = foo;
foo2.name; // "foo"

var bar = function baz() {};
bar.name; // "baz"

console.log(foo === foo2); // true
console.log(typeof baz); // undefined
console.log(bar === baz); // false (errors because baz == undefined)
```

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

Следующий пример демонстрирует создание безымянной (анонимной) функции и присвоение её переменной `x`. Функция возвращает квадрат переданного значения:

```js
var x = function (y) {
  return y \* y;
};
```

Преимущественно анонимные функции используются как колбэк-функции.

```js
button.addEventListener("click", function (event) {
  console.log("button is clicked!");
});
```

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

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

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

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

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

* `Functions and function scope` (en-US)
* `Function`
* `function statement`
* `function* statement`
* `function* expression`
* `GeneratorFunction`


Деструктурирующее присваивание - JavaScript

Деструктурирующее присваивание
==============================

Синтаксис **деструктурирующего присваивания** в выражениях JavaScript позволяет извлекать данные из массивов или объектов при помощи синтаксиса, подобного объявлению массива или литералов в объекте.

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

```js
var a, b, rest;
[a, b] = [1, 2];
console.log(a); // 1
console.log(b); // 2

[a, b, ...rest] = [1, 2, 3, 4, 5];
console.log(a); // 1
console.log(b); // 2
console.log(rest); // [3, 4, 5]

({ a, b } = { a: 1, b: 2 });
console.log(a); // 1
console.log(b); // 2

({ a, b, ...rest } = { a: 1, b: 2, c: 3, d: 4 });
console.log(a); // 1
console.log(b); // 2
console.log(rest); // { c:3, d:4 }
```

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

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

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

Данная возможность подобна таковой, присутствующей в языках Perl и Python.

Разбор массивов
---------------

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

```js
var foo = ["one", "two", "three"];

// без деструктурирования
var one = foo[0];
var two = foo[1];
var three = foo[2];

// с деструктурированием
var [one, two, three] = foo;
```

### Обмен значений переменных

После выполнения фрагмента кода, значение *b* будет 1, *a* будет 3. Без деструктурирующего присваивания, для обмена значений требуется дополнительная временная переменная (или что-то наподобие XOR-обмена).

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

[a, b] = [b, a];
```

### Возврат нескольких значений

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

```js
function f() {
  return [1, 2];
}
```

Как вы видите, возвращаемые результаты имеют вид массива, значения которого заключены в квадратные скобки. Вы можете возвращать неограниченное количество результатов таким образом. В следующем примере, `f()` возвращает `[1, 2]` как результат:

```js
var a, b;
[a, b] = f();
console.log("A is " + a + " B is " + b);
```

Оператор `[a, b] = f()` присваивает результаты функции переменным в квадратных скобках: *a* будет присвоено 1, *b* будет присвоено 2.

Вы также можете использовать результат функции в виде массива:

```js
var a = f();
console.log("A is " + a);
```

В данном случае *a* будет массивом с элементами 1 и 2.

### Игнорирование некоторых значений

Вы также можете проигнорировать не нужные значения:

```js
function f() {
  return [1, 2, 3];
}

var [a, , b] = f();
console.log("A is " + a + " B is " + b);
```

После выполнения кода, a будет 1, b будет 3. Значение 2 игнорируется. Таким же образом вы можете игнорировать любые (или все) значения. Например:

```js
[, ,] = f();
```

### Получение значений из результата регулярного выражения

Когда метод `exec()` регулярного выражения находит совпадение, он возвращает массив, содержащий первый совпадающий фрагмент строки и далее группы, определённые в регулярном выражении. Деструктурирующее присваивание упрощает получение данных из этих групп, игнорируя первый фрагмент:

```js
var url = "https://developer.mozilla.org/en-US/Web/JavaScript";

var parsedURL = /^(\w+)\:\/\/([^\/]+)\/(.\*)$/.exec(url);
var [, protocol, fullhost, fullpath] = parsedURL;

console.log(protocol); // выведет "https"
```

Разбор объектов
---------------

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

```js
var o = { p: 42, q: true };
var { p, q } = o;

console.log(p); // 42
console.log(q); // true

// Объявление новых переменных
var { p: foo, q: bar } = o;

console.log(foo); // 42
console.log(bar); // true
```

### Загрузка модулей

Деструктурирующее присваивание помогает загружать специфичные наборы модулей, как в Add-on SDK:

```js
const { Loader, main } = require("toolkit/loader");
```

### Вложенный объект и разбор массива

```js
var metadata = {
  title: "Scratchpad",
  translations: [
    {
      locale: "de",
      localization\_tags: [],
      last\_edit: "2014-04-14T08:43:37",
      url: "/de/docs/Tools/Scratchpad",
      title: "JavaScript-Umgebung",
    },
  ],
  url: "/ru/docs/Tools/Scratchpad",
};

var {
  title: englishTitle,
  translations: [{ title: localeTitle }],
} = metadata;

console.log(englishTitle); // "Scratchpad"
console.log(localeTitle); // "JavaScript-Umgebung"
```

### Деструктурирование во время обхода

```js
var people = [
  {
    name: "Mike Smith",
    family: {
      mother: "Jane Smith",
      father: "Harry Smith",
      sister: "Samantha Smith",
    },
    age: 35,
  },
  {
    name: "Tom Jones",
    family: {
      mother: "Norah Jones",
      father: "Richard Jones",
      brother: "Howard Jones",
    },
    age: 25,
  },
];

for (var {
  name: n,
  family: { father: f },
} of people) {
  console.log("Name: " + n + ", Father: " + f);
}

// "Name: Mike Smith, Father: Harry Smith"
// "Name: Tom Jones, Father: Richard Jones"
```

### Получение полей объекта-параметра функции

```js
function userId({ id }) {
  return id;
}

function whois({ displayName, fullName: { firstName: name } }) {
  console.log(displayName + " is " + name);
}

var user = {
  id: 42,
  displayName: "jdoe",
  fullName: {
    firstName: "John",
    lastName: "Doe",
  },
};

console.log("userId: " + userId(user)); // "userId: 42"
whois(user); // "jdoe is John"
```

В приведённом примере извлекаются поля `id`, `displayName` и `firstName` из объекта пользователь.

### Деструктурирование вычисляемых имён свойств

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

```js
let key = "z";
let { [key]: foo } = { z: "bar" };

console.log(foo); // "bar"
```

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

| Specification |
| --- |
| ECMAScript Language Specification # sec-destructuring-assignment |
| ECMAScript Language Specification # sec-destructuring-binding-patterns |

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

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


Оператор Запятая - JavaScript

Оператор Запятая
================

**Оператор запятая** выполняет каждый из его операндов (слева направо) и возвращает значение последнего операнда.

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

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

expr1, expr2, expr3...
```

Параметры
---------

`expr1`, `expr2, expr3...`

Любые выражения.

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

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

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

Если `a` это двумерный массив элементов размерностью 10 х 10, то приведённый ниже код использует оператор запятая для одновременного изменения двух переменных за раз.

Следующий код выводит в консоль значения диагональных элементов массива:

```js
for (let i = 0, j = 9; i <= 9; i++, j--)
  console.log("a[" + i + "][" + j + "] = " + a[i][j]);
```

Заметьте, что запятая при объявлении переменной `var`, `let` или `const` **не** является оператором запятая, так как в данном случае она находится не в выражении. Скорее, это спец символ в объявлении переменных, комбинирующий их множество в одно выражение. Практически, эта запятая ведёт себя почти так же, как и запятая.

```js
// подобное объявление запрещено в строгом режиме(strict mode)

(a = b = 3), (c = 4); // возвращает 4 в консоль
console.log(a); // 3
x = ((y = 5), (z = 6)); // возвращает 6 в консоль
console.log(x); // 6
```

Оператор запятая полностью отличается от запятой в массивах, объектах, аргументах и параметрах функции.

### Вычисления и возврат значения

Другой пример использования оператора запятой – вычисления перед возвратом значения. Как было указано ранее, будет возвращён только последний элемент, но все предыдущие также будут вычислены. Таким образом можно сделать:

```js
function myFunc() {
  let x = 0;

  return (x += 1), x; // то же самое, что return ++x;
}
```

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

| Specification |
| --- |
| ECMAScript Language Specification # sec-comma-operator |

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

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

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

* for loop


Property accessors - JavaScript

Property accessors
==================

Доступ к свойствам объекта можно получить, используя точечную и скобочную записи.

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

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

object.property
object["property"]
```

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

Можно думать об объекте как об ассоциативном массиве (или *карте, словаре, хэш-таблице, таблице поиска*). *Ключи* в таком массиве - это имена свойств объекта.

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

Есть два способа доступа к свойствам: точечная и скобочная записи.

### Точечная запись

В записи `object.property`, property должно быть действительным идентификатором. (В стандарте ECMAScript, имена свойств технически называются "IdentifierNames", а не "Identifiers", поэтому зарезервированные слова могут быть использованы в их качестве, но это не рекомендуется). Например, `object.$1` является верной записью, а `object.1` - нет.

```js
const variable = object.property_name;

object.property_name = value;
```

```js
const object = {};

object.$1 = 'foo';
console.log(object.$1);  // 'foo'

object.1 = 'bar';        // SyntaxError
console.log(object.1);   // SyntaxError
```

Здесь метод с именем `createElement` считывается с объекта `document` и вызывается.

```js
document.createElement("pre");
```

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

```js
// SyntaxError, здесь считается, что 77. это число,
// поэтому такая запись эквивалентна (77.)toExponentional()
// что является ошибкой
77.toExponentional()
// Рабочие варианты:
77.toExponential()
77
.toExponential()
;(77).toExponential()
// Здесь первая точка относится к числу, вторая вызывает метод
// то есть эта запись равносильна (77.).toExponential()
77..toExponential()
// Эквивалентно (77.0).toExponential()
77.0.toExponential()
```

### Скобочная запись

В записи `object[property_name]`, *`property_name` -* это выражение, вычисляющееся в строку или символ. Это может быть любая строка, не обязательно действительный идентификатор, например `'1foo'`, '`!bar!'` или даже `' '` (пробел).

```js
const variable = object[property_name];
object[property_name] = value;
```

Пример, аналогичный примеру в предыдущем пункте:

```js
document["createElement"]("pre");
```

Пробел перед скобкой допускается:

```js
document["createElement"]("pre");
```

### Имена свойств

Имена свойств могут быть строками или символами. Любое другое значение приводится к строке. Следующий код выводит `'value'`, поскольку число `1` приводится к строке `'1'`.

```js
const object = {};
object["1"] = "value";
console.log(object[1]);
```

Этот пример также выводит `'value',` так как и `foo`, и bar приводятся к одной и той же строке.

```js
const foo = { unique\_prop: 1 };
const bar = { unique\_prop: 2 };
const object = {};

object[foo] = "value";
console.log(object[bar]);
```

В движке SpiderMonkey JavaScript это строка `'[object Object]'`.

### Привязка методов

Метод не привязан к содержащему его объекту. Это значит, что значение `this` в методах объекта не всегда указывает на него. Вместо этого, `this` "передаётся" при вызове метода. Смотрите подробнее `this`.

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

### Скобочная запись или `eval`

Новички JavaScript часто делают ошибку, используя eval там, где можно просто использовать скобочную запись.

Например, следующий синтаксис можно часто увидеть в скриптах.

```js
x = eval("document.forms.form\_name.elements." + strFormControl + ".value");
```

Функция `eval()` очень медленная и её использования следует избегать, когда это возможно. Кроме того, строка `strFormControl` при таком использовании обязаны содержать действительный идентификатор, что не является обязательным для `id` полей формы, то есть, например, поле с id 1 не получится получить такой записью. Лучше вместо этого использовать скобочную запись:

```js
x = document.forms["form\_name"].elements[strFormControl].value;
```

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

| Specification |
| --- |
| ECMAScript Language Specification # sec-property-accessors |

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

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

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

* `Object`


await - JavaScript

await
=====

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

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

* Learn more
* See full compatibility
* Report feedback
Оператор `await` используется для ожидания окончания `Promise`. Может быть использован только внутри `async function` или на верхнем уровне модуля.

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

[rv] = await expression;
```

`expression`

`Promise` или любое другое значение для ожидания разрешения.

`rv`

Возвращает полученное из `Promise` значение, либо само значение, если оно не является `Promise.`

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

Оператор `await` заставляет функцию, объявленную с использованием оператора `async`, ждать выполнения `Promise` и продолжать выполнение после возвращения `Promise` значения. Впоследствии возвращает полученное из `Promise` значение. Если типом значения, к которому был применён оператор `await`, является не `Promise`, то значение приводится к успешно выполненному `Promise`.

Если `Promise` отклоняется, то `await` генерирует исключение с отклонённым значением.

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

`await` ожидает разрешения `Promise` и возвращает полученное значение.

```js
function resolveAfter2Seconds(x) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}

async function f1() {
  var x = await resolveAfter2Seconds(10);
  console.log(x); // 10
}
f1();
```

Если типом значения является не `Promise`, значение преобразуется к успешно выполненному `Promise`.

```js
async function f2() {
  var y = await 20;
  console.log(y); // 20
}
f2();
```

Если `Promise` отклонён, то выбрасывается исключение с переданным значением.

```js
async function f3() {
  try {
    var z = await Promise.reject(30);
  } catch (e) {
    console.log(e); // 30
  }
}
f3();
```

Обработка отклонённого `Promise` без `try/catch` блока.

```js
var response = await promisedFunction().catch((err) => {
  console.log(err);
});
// response получит значение undefined, если Promise будет отклонён
```

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

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

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

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

See also
--------

* `async function`
* `async function expression`
* `AsyncFunction` object


async function expression - JavaScript

async function expression
=========================

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

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

* Learn more
* See full compatibility
* Report feedback
Ключевое слово **`async function`** используется для определения асинхронной функции внутри выражений.

Вы также можете определить асинхронные функции при помощи инструкции async function.

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

async function [name]([param1[, param2[, ..., paramN]]]) {
   statements
}
```

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

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

`name`

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

`paramN`

Имя аргумента, передаваемого функции.

`statements`

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

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

Выражение `async function` очень похоже, и имеет почти тот же синтаксис, что и `async function statement`. Главное отличие между выражениями async `function` и объявлениями async `function` заключается в *имени функции,* которое может быть опущено в выражении `async function` для создания *анонимной* функции. Выражение `async function` можно использовать в виде IIFE (Immediately Invoked Function Expression), и оно будет запущено сразу после объявления. Смотрите также главу о функциях.

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

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

```js
function resolveAfter2Seconds(x) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}

(async function (x) {
  // выражение асинхронной функции в виде IIFE
  var a = resolveAfter2Seconds(20);
  var b = resolveAfter2Seconds(30);
  return x + (await a) + (await b);
})(10).then((v) => {
  console.log(v); // выведет 60 после 2 секунд.
});

var add = async function (x) {
  // назначение выражения асинхронной функции переменной
  var a = await resolveAfter2Seconds(20);
  var b = await resolveAfter2Seconds(30);
  return x + a + b;
};

add(10).then((v) => {
  console.log(v); // выведет 60 после 4 секунд.
});
```

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

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

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

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

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

* `async function`
* `AsyncFunction` object
* `await`


Условный (тернарный) оператор - JavaScript

Условный (тернарный) оператор
=============================

**Условный (тернарный) оператор** - единственный оператор в JavaScript, принимающий три операнда: условие, за которым следует знак вопроса (?), затем выражение, которое выполняется, если условие истинно, сопровождается двоеточием (:), и, наконец, выражение, которое выполняется, если условие ложно. Он часто используется в качестве сокращённого варианта инструкции `if...else`.

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

условие ? выражение1 : выражение2
```

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

`условие`

Выражение, принимающее значение `true` или `false`.

`выражение1`, `выражение2`

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

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

Оператор возвращает значение `выражения1`, если `условие` верно, и значение `выражения2` в противном случае. Например, чтобы вывести сообщение, текст которого зависит от значения переменной `isMember`, можно использовать такое выражение:

```js
function getFee(isMember) {
  return "The fee is " + (isMember ? "$2.00" : "$10.00");
}

console.log(getFee(true));
// Выводит в консоль: "$2.00"

console.log(getFee(false));
// Выводит в консоль: "$10.00"
```

Также можно присваивать значения переменным на основе результатов работы тернарного оператора :

```js
const elvisLives = Math.PI > 4 ? "Да" : "Нет";
console.log(elvisLives); // "Нет"
```

Возможны множественные тернарные операции (обратите внимание: условный оператор ассоциативен справа):

```js
const firstCheck = false;
const secondCheck = false;
const access = firstCheck
  ? "Доступ запрещён"
  : secondCheck
    ? "Доступ запрещён"
    : "Доступ разрешён";

console.log(access); // выводит в консоль "Доступ разрешён"
```

Тернарные операции можно использовать и сами по себе - для выполнения различных операций:

```js
const age = 16;
let stop = false;

age > 18 ? location.assign("continue.html") : (stop = true);
```

Также возможно выполнять несколько операций на каждое сравнение, разделив их запятыми:

```js
const age = 23;
let stop = false;

age > 18
  ? (alert("Хорошо, вы можете продолжить."), location.assign("continue.html"))
  : ((stop = true), alert("Простите, вы ещё так юны!"));
```

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

```js
const age = 16;

const url =
  age > 18
    ? (alert("Хорошо, вы можете продолжить."),
      // alert вернёт "undefined", но это будет проигнорировано, потому что
      // не является последним в списке значений, разделённых запятой
      "continue.html") // значение будет присвоено, если age > 18
    : (alert("Вы слишком молоды!"), alert("Простите :-("), "stop.html"); // значение будет присвоено, если age < 18

location.assign(url); // "stop.html"
```

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

| Specification |
| --- |
| ECMAScript Language Specification # sec-conditional-operator |

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

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

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

* Инструкция if...else


yield - JavaScript

yield
=====

Ключевое слово `yield` используется для остановки и возобновления функций-генераторов (`function*` или legacy generator function (en-US)).

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

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

 [rv] = yield [[выражение]];
```

`выражение`

Возвращаемое выражение. Если не указано, то возвращается значение `undefined`.

`rv`

Возвращает необязательное значение, которое передаётся в `next()` генератора, чтобы возобновить его выполнение.

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

Ключевое слово `yield` вызывает остановку функции-генератора и возвращает текущее значение выражения, указанного после ключевого слова `yield`. Его можно рассматривать как аналог ключевого слова `return` в функции-генераторе.

На самом деле ключевое слово `yield` возвращает объект с двумя параметрами, `value` и `done`. При этом, `value` является результатом вычисления выражения после `yield`, а `done` указывает, была ли завершена функция-генератор.

Во время остановки на операторе `yield`, выполнение кода в функции-генераторе не возобновится, пока не будет вызван метод `next()` возвращаемого функцией объекта-генератора. Это предоставляет непосредственный контроль за выполнением генератора и возвратом его значений.

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

Следующий фрагмент кода содержит определение функции-генератора и вспомогательной функции:

```js
function\* foo() {
  var index = 0;
  while (index <= 2)
    // при достижении 2, done в yield станет true, а value undefined;
    yield index++;
}
```

После того как тело функции-генератора определено, оно может использоваться для получения итератора:

```js
var iterator = foo();
console.log(iterator.next()); // { value:0, done:false }
console.log(iterator.next()); // { value:1, done:false }
console.log(iterator.next()); // { value:2, done:false }
console.log(iterator.next()); // { value:undefined, done:true }
```

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

| Specification |
| --- |
| ECMAScript Language Specification # prod-YieldExpression |

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

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

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

* Итераторы
* Генераторы


delete - JavaScript

delete
======

Аннотация
---------

Оператор `delete` удаляет свойство из объекта.

| Оператор |
| --- |
| Реализован в: | JavaScript 1.2 |
| Версия ECMAScript: | ECMA-262 1-ый выпуск |

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

`delete выражение`

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

delete object.property
delete object['property']
delete object[index]
delete property // удаляет свойства глобального объекта, или,
                // используя инструкцию with, свойства объекта, на который ссылается инструкция
```

Если результат вычисления *выражения* не является свойством (объекта), `delete` ничего не делает.

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

`object`

Имя объекта или выражение, результатом вычисления которого является объект.

`property`

Удаляемое свойство.

`index`

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

### Возвращаемое значение

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

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

Если оператор `delete` успешно выполняет удаление, он полностью удаляет свойство из объекта. Однако, если свойство с таким же именем существует в цепочке прототипов, объект унаследует это свойство из прототипа.

`delete` эффективен только применительно к свойствам объектов. Он не оказывает никакого влияния на имена переменных и функций.
 Присвоение значения свойству без указания объекта (без оператора var) иногда неверно характеризуется, как глобальная переменная, (например `x = 5`). На самом деле происходит присвоение значения свойству глобального объекта.

`delete` не может удалить определённые свойства встроенных объектов (таких как Object, Array, Math и так далее). В спецификации ECMA-262 они обозначены как *DontDelete.*

```js
x = 42; // создаёт свойство x в глобальном объекте
var y = 43; // объявляет новую переменную, y
myobj = {};
myobj.h = 4; // создаёт свойство h в myobj
myobj.k = 5; // создаёт свойство k в myobj

delete x; // возвращает true (x - свойство глобального объекта и может быть удалено)
delete y; // возвращает false (delete не влияет на имена переменных)
delete Math.PI; // возвращает false (delete не влияет на определённые встроенные свойства)
delete myobj.h; // возвращает true (свойства, определённые пользователем могут быть удалены)

with (myobj) {
  delete k; // возвращает true (эквивалентно delete myobj.k)
}

delete myobj; // возвращает true (myobj это свойство глобального объекта, не переменная, поэтому может быть удалено)
```

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

```js
function Foo() {}
Foo.prototype.bar = 42;
var foo = new Foo();
delete foo.bar; // возвращает true, но безрезультатно, так как bar - наследуемое свойство
alert(foo.bar); // выводит 42, свойство все ещё наследуется
delete Foo.prototype.bar; // удаляет свойство из прототипа
alert(foo.bar); // выводит "undefined", свойство больше не наследуется
```

### Удаление элементов массива

Когда с помощью оператора delete удаляется элемент массива, длина массива не меняется. Например, если вы удалите `a[3]`, `a[4]` по прежнему `a[4]`, а `a[3]` не определено. Так будет даже если вы удалите последний элемент массива (`delete a[a.length-1]`).

Когда оператор `delete` удаляет элемент массива, этот элемент больше не существует в массиве. В следующем примере, `trees[3]` удаляется с помощью `delete`.

```js
const trees = ["redwood", "bay", "cedar", "oak", "maple"];
delete trees[3];
console.log(3 in trees); // false
```

Если вы хотите, чтобы элемент массива существовал, но имел значение undefined, используйте значение `undefined` вместо оператора `delete`. В следующем примере, `trees[3]` принимает значение undefined, но элемент массива все ещё существует:

```js
const trees = ["redwood", "bay", "cedar", "oak", "maple"];
trees[3] = undefined;
console.log(3 in trees); // true
```

Проблема кроссбраузерности
--------------------------

Несмотря на то, что стандарт ECMAScript оставляет порядок итерации по свойствам объектов на усмотрение реализующей стороны, может оказаться так, что все основные браузеры поддерживают порядок итерации, основанный на принципе "свойство добавленное в объект раньше идёт раньше" (по крайней мере для свойств не находящихся в прототипе). Однако, в случае с Internet Explorer, когда кто-нибудь использует `delete` с каким-либо свойством, это приводит к некоторым неожиданным результатам, заставляя другие браузеры отказаться от использования простых объектов, таких как литералы объектов, в качестве ассоциативных массивов. В Internet Explorer, когда значение свойства установлено в undefined, после удаления этого свойства, если кто-нибудь позже добавит свойство с таким же именем, оно окажется в своей *старой* позиции, а не в конце итерационной последовательности, как ожидается.

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

Внешние ссылки
--------------

* Глубокий анализ оператора delete


Декремент (--) - JavaScript

Декремент (--)
==============

Оператор декремента (`--`) уменьшает (вычитает единицу) свой операнд и возвращает значение.

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

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

Operator: x-- or --x
```

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

Если используется постфикс, с оператором после операнда (например, x--), оператор декремента уменьшает и возвращает значение перед уменьшением.

Если используется префикс, с оператором перед операндом (например, --x), оператор декремента уменьшает и возвращает значение после уменьшения.

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

### Постфиксный декремент

```js
let x = 3;
y = x--;

// y = 3
// x = 2
```

### Префиксный декремент

```js
let a = 2;
b = --a;

// a = 1
// b = 1
```

Характеристики
--------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-postfix-decrement-operator |

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

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

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

* Addition operator
* Subtraction operator (en-US)
* Division operator (en-US)
* Multiplication operator (en-US)
* Remainder operator (en-US)
* Exponentiation operator (en-US)
* Increment operator (en-US)
* Unary negation operator (en-US)
* Unary plus operator (en-US)


Оператор new - JavaScript

Оператор new
============

**Оператор** (операторная функция) **`new`** создаёт экземпляр объекта, встроенного или определённого пользователем, имеющего конструктор.

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

new constructor[([arguments])]
```

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

`constructor`

Функция, задающая тип объекта.

`arguments`

Список параметров, с которыми будет вызван конструктор.

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

Создание объекта, определённого пользователем, требует два шага:

1. Написать функцию, которая задаст тип объекта.
2. Создать экземпляр объекта, используя `new`.

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

Когда исполняется `new Foo(...)` , происходит следующее:

1. Создаётся новый объект, наследующий `Foo.prototype.`
2. Вызывается конструктор — функция `Foo` с указанными аргументами и `this`, привязанным к только что созданному объекту. `new Foo` эквивалентно `new Foo()`, то есть если аргументы не указаны, `Foo` вызывается без аргументов.
3. Результатом выражения new становится объект, возвращённый конструктором. Если конструктор не возвращает объект явно, используется объект из п. 1. (Обычно конструкторы не возвращают значение, но они могут делать это, если нужно переопределить обычный процесс создания объектов.)

Всегда можно добавить свойство к уже созданному объекту. Например, `car1.color = "black"` добавляет свойство `color` к объекту `car1`, и присваивает ему значение "`black`". Это не затрагивает другие объекты. Чтобы добавить свойство ко всем объектам типа, нужно добавлять его в определение типа Car.

Добавить свойство к ранее определённому типу можно используя свойство `Function.prototype` (en-US). Это определит свойство для всех объектов, созданных этой функцией, а не только у какого-либо экземпляра. Следующий пример добавляет свойство color со значением `null` всем объектам типа `car`, а потом меняет его на "`black`" только у экземпляра `car1`. Больше информации в статье prototype (en-US).

```js
function Car() {}
car1 = new Car();

console.log(car1.color); // undefined

Car.prototype.color = null;
console.log(car1.color); // null

car1.color = "black";
console.log(car1.color); // black
```

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

### Тип объекта и экземпляры объекта

Предположим, нам нужен тип объекта для автомобилей. Этот тип должен называться `car`, и иметь свойства: марка, модель и год.

```js
function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}
```

Теперь можно создать экземпляр типа car:

```js
var mycar = new Car("Eagle", "Talon TSi", 1993);
```

Это выражение создаёт экземпляр `mycar` и присваивает его свойствам указанные значения. Таким образом, `mycar.make` принимает значение "Eagle", `mycar.year` принимает значение 1993, и так далее.

Можно создать любое количество экземпляров `car` с помощью оператора `new`. Например:

```js
var kenscar = new Car("Nissan", "300ZX", 1992);
```

### Объект в качестве свойства

Предположим, есть объект `person`:

```js
function Person(name, age, sex) {
  this.name = name;
  this.age = age;
  this.sex = sex;
}
```

Создадим два экземпляра:

```js
var rand = new Person("Rand McNally", 33, "M");
var ken = new Person("Ken Jones", 39, "M");
```

Изменим определение `car`, добавив свойство, указывающее владельца — `owner`:

```js
function Car(make, model, year, owner) {
  this.make = make;
  this.model = model;
  this.year = year;
  this.owner = owner;
}
```

Создадим экземпляры car:

```js
var car1 = new Car("Eagle", "Talon TSi", 1993, rand);
var car2 = new Car("Nissan", "300ZX", 1992, ken);
```

Вместо строковых или численных значений можно передать объект как параметр. Чтобы узнать имя владельца `car2`, получим доступ к свойству:

```js
car2.owner.name;
```

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

| Specification |
| --- |
| ECMAScript Language Specification # sec-new-operator |

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

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

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

* `Function`
* `Reflect.construct()`


function* expression - JavaScript

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

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

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

function* [имя]([параметр1[, параметр2[, ..., параметрN]]]) {
   инструкции
}
```

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

`имя`

Имя функции. Может быть опущено, в этом случае функция будет *анонимной*. Имя локально для тела функции.

`параметрN`

Имя аргумента, передаваемого в функцию. Функция может иметь до 255 аргументов.

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

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

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

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

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

В следующем примере определяется безымянная функция-генератор и присваивается переменной `x`. Функция возвращает квадрат своего аргумента:

```js
var x = function\* (y) {
  yield y \* y;
};
```

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

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

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

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

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

* `function* statement`
* Объект `GeneratorFunction`
* Протоколы перебора: Итератор
* `yield`
* `yield*`
* Объект `Function`
* `function statement`
* `function expression`
* `Функции`


Приоритет операторов - JavaScript

Приоритет операторов
====================

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

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

Ассоциативность
---------------

Ассоциативность определяет порядок, в котором обрабатываются операторы с одинаковым приоритетом. Например, рассмотрим выражение:
```

a OP b OP c
```

Левая ассоциативность (слева направо) означает, что оно обрабатывается как `(a OP b) OP c`, в то время как правая ассоциативность (справа налево) означает, что они интерпретируются как `a OP (b OP c)`. Операторы присваивания являются право-ассоциативными, так что вы можете написать:

```js
a = b = 5;
```

с ожидаемым результатом, что `a` и `b` будут равны 5. Это происходит, потому что оператор присваивания возвращает тот результат, который присваивает. Сначала `b` становится равным 5, затем `a` принимает значение `b`.

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

```js
3 > 2 && 2 > 1;
// вернёт true

3 > 2 > 1;
// вернёт false, потому что 3 > 2 возвращает true, в свою очередь true > 1 вернёт false
// Добавление скобок значительно повышает читаемость выражения: (3 > 2) > 1
```

Таблица
-------

Операторы упорядочены с самого высокого (18) до самого низкого (1) приоритета.

Обратите внимание, что spread-оператор (`...`) намеренно не включен в таблицу, потому что он вообще не является оператором и правильно говорить `spread-синтаксис`. Подробнее можно почитать в ответе на Stack Overflow (en).

| Приоритет | Тип оператора | Ассоциативность | Конкретные операторы |
| --- | --- | --- | --- |
| 18 | `Группировка` | не определено | `( … )` |
| 17 | `Доступ к свойствам` | слева направо | `… . …` |
| `Доступ к свойствам с возможностью вычисления` | `… [ … ]` |
| `new` (со списком аргументов) | не определено | `new … ( … )` |
| Вызов функции | слева направо | `… ( … )` |
| Оператор опциональной последовательности (?.) | `?.` |
| 16 | `new` (без списка аргументов) | справа налево | `new …` |
| 15 | `Постфиксный инкремент` (en-US) | не определено | `… ++` |
| `Постфиксный декремент` (en-US) | `… --` |
| 14 | Логическое отрицание (!) (en-US) | справа налево | `! …` |
| Побитовое отрицание (~) (en-US) | `~ …` |
| Унарный плюс (en-US) | `+ …` |
| Унарный минус (en-US) | `- …` |
| Префиксный инкремент (en-US) | `++ …` |
| Префиксный декремент (en-US) | `-- …` |
| typeof | `typeof …` |
| void | `void …` |
| delete | `delete …` |
| await | `await …` |
| 13 | Возведение в степень (\*\*) (en-US) | справа налево | `… ** …` |
| 12 | Умножение (\*) (en-US) | слева направо | `… * …` |
| Деление (/) (en-US) | `… / …` |
| Остаток от деления (%) (en-US) | `… % …` |
| 11 | Сложение (+) (en-US) | слева направо | `… + …` |
| Вычитание (-) (en-US) | `… - …` |
| 10 | Побитовый сдвиг влево (<<) | слева направо | `… << …` |
| Побитовый сдвиг вправо (>>) (en-US) | `… >> …` |
| Сдвиг вправо с заполнением нулей (>>>) (en-US) | `… >>> …` |
| 9 | Меньше (<) (en-US) | слева направо | `… < …` |
| Меньше или равно (<=) (en-US) | `… <= …` |
| Больше (>) (en-US) | `… > …` |
| Больше или равно (>=) (en-US) | `… >= …` |
| in | `… in …` |
| instanceof | `… instanceof …` |
| 8 | Равенство (==) (en-US) | слева направо | `… == …` |
| Неравенство (!=) (en-US) | `… != …` |
| Строгое равенство (===) (en-US) | `… === …` |
| Строгое неравенство (!==) (en-US) | `… !== …` |
| 7 | Побитовое «И» (&) (en-US) | слева направо | `… & …` |
| 6 | Побитовое исключающее «ИЛИ» (^) (en-US) | слева направо | `… ^ …` |
| 5 | Побитовое «ИЛИ» (|) (en-US) | слева направо | `… | …` |
| 4 | Логическое «И» (&&) (en-US) | слева направо | `… && …` |
| 3 | Логическое «ИЛИ» (||) (en-US) | слева направо | `… || …` |
| Оператор нулевого слияния (??) | `… ?? …` |
| 2 | Присваивание (en-US) | справа налево | `… = …` |
| `… += …` |
| `… -= …` |
| `… **= …` |
| `… *= …` |
| `… /= …` |
| `… %= …` |
| `… <<= …` |
| `… >>= …` |
| `… >>>= …` |
| `… &= …` |
| `… ^= …` |
| `… |= …` |
| `… &&= …` |
| `… ||= …` |
| `… ??= …` |
| Условный (тернарный) оператор | справа налево | `… ? … : …` |
| yield | справа налево | `yield …` |
| yield\* | `yield* …` |
| 1 | Запятая / Последовательность | слева направо | `… , …` |


Сложение (+) - JavaScript

Сложение (+)
============

Оператор сложения (+) создаёт сумму числовых операндов или конкатенацию строк.

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

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

```js
x + y;
```

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

### Сложение чисел

```js
// Number + Number -> addition
1 + 2; // 3

// Boolean + Number -> addition
true + 1; // 2

// Boolean + Boolean -> addition
false + false; // 0
```

### Сложение строк

```js
// String + String -> concatenation
"foo" + "bar"; // "foobar"

// Number + String -> concatenation
5 + "foo"; // "5foo"

// String + Boolean -> concatenation
"foo" + false; // "foofalse"
```

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

| Specification |
| --- |
| ECMAScript Language Specification # sec-addition-operator-plus |

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

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

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

* Subtraction operator (en-US)
* Division operator (en-US)
* Multiplication operator (en-US)
* Remainder operator (en-US)
* Exponentiation operator (en-US)
* Increment operator (en-US)
* Decrement operator
* Unary negation operator (en-US)
* Unary plus operator (en-US)


in operator - JavaScript

in operator
===========

**Оператор `in`** возвращает `true`, если свойство содержится в указанном объекте или в его цепочке прототипов.

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

prop in object
```

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

`prop`

Строка или symbol, представляющий название свойства или индекс массива (non-symbols будут конвертированы в строки).

`object`

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

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

В примере ниже показаны некоторые способы использования оператора `in`.

```js
// Массивы
var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
0 in trees; // true
3 in trees; // true
6 in trees; // false
"bay" in trees; // false (вы должны указать индекс элемента в массиве, а не значение в этом индексе)
"length" in trees; // true (length является свойством Array)

// Уже существующие объекты
"PI" in Math; // true

// Пользовательские объекты
var mycar = { make: "Honda", model: "Accord", year: 1998 };
"make" in mycar; // true
"model" in mycar; // true
```

Вы должны указать объект справа от оператора `in`. Например, вы можете указать строку, созданную через конструктор объекта `String`, но вы не можете указать строковый литерал.

```js
var color1 = new String("green");
"length" in color1; // returns true

var color2 = "coral";
// сгенерирует ошибку (color2 is not a String object)
"length" in color2;
```

### Использование оператора `in` с неопределёнными или с уже удалёнными свойствами

Если вы удалили свойство при помощи оператора `delete`, то оператор `in` возвратит `false` для этого свойства.

```js
var mycar = { make: "Honda", model: "Accord", year: 1998 };
delete mycar.make;
"make" in mycar; // false

var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
delete trees[3];
3 in trees; // false
```

Если вы зададите свойству значение `undefined`, но не удалите его, то для этого свойства оператор `in` вернёт значение `true`.

```js
var mycar = { make: "Honda", model: "Accord", year: 1998 };
mycar.make = undefined;
"make" in mycar; // true
```

```js
var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
trees[3] = undefined;
3 in trees; // returns true
```

### Наследуемые свойства

Оператор `in` возвратит `true` для свойств, которые унаследованы по цепочке прототипов. (Если вы хотите проверить только не наследованные свойства, используйте `Object.prototype.hasOwnProperty()`.)

```js
"toString" in {}; // true
```

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

| Specification |
| --- |
| ECMAScript Language Specification # sec-relational-operators |

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

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

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

* `delete`
* `Object.prototype.hasOwnProperty()`
* `Reflect.has()` (en-US)
* Enumerability and ownership of properties (en-US)


void operator - JavaScript

void operator
=============

**Оператор `void`** вычисляет переданное *выражение* и возвращает `undefined`.

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

void expression
```

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

Этот оператор позволяет вставлять выражения, которые производят дополнительные действия, в места, где ожидается `undefined`.

Оператор `void` часто используется для получения примитивного значения `undefined`, используя `"void(0)"` (что эквивалентно `"void 0"`). В подобных случаях можно просто использовать глобальную переменную `undefined` (предполагая, что её значение по умолчанию не было изменено).

Самовызывающаяся функция (IIFE)
-------------------------------

С оператором void можно использовать самовызывающиеся функции.

```js
void (function iife() {
  var bar = function () {};
  var baz = function () {};
  var foo = function () {
    bar();
    baz();
  };
  var biz = function () {};

  foo();
  biz();
})();
```

JavaScript URIs
---------------

Когда браузер переходит по `javascript: URI`, он вычисляет код в `URI` и заменяет содержание страницы возвращённым значением, если оно не равно `undefined`. Можно воспользоваться оператором `void` для возврата `undefined`. Например:

```html
<a href="javascript:void(0);">Click here to do nothing</a>

<a href="javascript:void(document.body.style.backgroundColor='green');">
  Click here for green background
</a>
```

Однако заметим, что не рекомендуется использовать псевдо-протокол `javascript:`. Лучше прибегнуть к другим альтернативам, таким, как обработчики событий.

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

| Specification |
| --- |
| ECMAScript Language Specification # sec-void-operator |

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

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

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

* `undefined`


BigInt - JavaScript

BigInt
======

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

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

* Learn more
* See full compatibility
* Report feedback
**`BigInt`** это встроенный объект, который предоставляет способ представлять целые числа больше 253 - 1, наибольшего числа, которое JavaScript может надёжно представить с `Number` примитивом. Это максимальное значение можно получить, обратившись к `Number.MAX_SAFE_INTEGER`.

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

`BigInt` создаётся путём добавления `n` в конец целочисленного литерала — `10n` — или вызовом функции `BigInt()`.

```js
const theBiggestInt = 9007199254740991n;

const alsoHuge = BigInt(9007199254740991);
// ↪ 9007199254740991n

const hugeString = BigInt("9007199254740991");
// ↪ 9007199254740991n

const hugeHex = BigInt("0x1fffffffffffff");
// ↪ 9007199254740991n

const hugeBin = BigInt(
  "0b11111111111111111111111111111111111111111111111111111",
);
// ↪ 9007199254740991n
```

В некотором смысле он похож на `Number`, но отличается в некоторых ключевых моментах — его нельзя использовать с методами во встроенном объекте `Math` и нельзя смешивать в операциях с любыми экземплярами Number.

**Предупреждение:** `Number` и `BigInt` нельзя смешивать в операциях — они должны быть приведены к тому же типу.

Будьте осторожны приводя значения туда и обратно, так как точность BigInt может быть потеряна при приведении к числу (`Number)`.

### Тип

При проверке с использованием оператора `typeof`, `BigInt` выдаёт тип `"bigint"`:

```js
typeof 1n === "bigint"; // true
typeof BigInt("1") === "bigint"; // true
```

При оборачивании в объект, BigInt будет представлен как обычный объект:

```js
typeof Object(1n) === "object"; // true
```

### Операторы

Следующие операторы могут использоваться с `BigInt` (или объектом-обёрткой `BigInt`): `+`, `*`, `-`, `**`, `%`.

Побитовые операции (en-US) также поддерживаются, кроме `>>>` (сдвиг вправо с заполнением нулями).

Не поддерживаемый унарный оператор (`+`) больше не ломает asm.js.

```js
const previousMaxSafe = BigInt(Number.MAX\_SAFE\_INTEGER);
// ↪ 9007199254740991n

const maxPlusOne = previousMaxSafe + 1n;
// ↪ 9007199254740992n

const theFuture = previousMaxSafe + 2n;
// ↪ 9007199254740993n, это работает!

const multi = previousMaxSafe \* 2n;
// ↪ 18014398509481982n

const subtr = multi – 10n;
// ↪ 18014398509481972n

const mod = multi % 10n;
// ↪ 2n

const bigN = 2n \*\* 54n;
// ↪ 18014398509481984n

bigN \* -1n
// ↪ –18014398509481984n
```

Оператор `/` также работает, как и ожидалось, с целыми числами. Однако, поскольку это BigInt, эта операция будет округляться в меньшую сторону, то есть она не будет возвращать какие-либо дробные цифры.

**Предупреждение:** Результат операции с дробным результатом будет округлён в **меньшую** сторону при использовании `BigInt`.

```js
const expected = 4n / 2n;
// ↪ 2n

const rounded = 5n / 2n;
// ↪ 2n, not 2.5n
```

### Сравнения

`BigInt` равен `Number` только при нестрогом сравнении.

```js
0n === 0;
// ↪ false

0n == 0;
// ↪ true
```

`Обычные числа` и `BigInt` можно сравнивать как обычно.

```js
1n < 2;
// ↪ true

2n > 1;
// ↪ true

2 > 2;
// ↪ false

2n > 2;
// ↪ false

2n >= 2;
// ↪ true
```

Они могут быть смешаны в массивах и отсортированы:

```js
const mixed = [4n, 6, -12n, 10, 4, 0, 0n];
// ↪ [4n, 6, -12n, 10, 4, 0, 0n]

mixed.sort();
// ↪ [-12n, 0, 0n, 10, 4n, 4, 6]
```

Обратите внимание, что сравнения с `обьектом`-обёрткой `BigInt` действуют как с другими объектами, указывая на равенство только когда сравнивается идентичный экземпляр объекта:

```js
0n === Object(0n); // false
Object(0n) === Object(0n); // false

const o = Object(0n);
o === o; // true
```

### Условные выражения

`BigInt` ведёт себя как `обычное число` в следующих случаях:

* Преобразуется в `Boolean` через функцию `Boolean`
* Используется с логическими операторами `Logical Operators` (en-US) `||`, `&&` и `!`
* В условном тесте, таком как `if statement`.

```js
if (0n) {
  console.log("Привет из if!");
} else {
  console.log("Привет из else!");
}

// ↪ "Привет из else!"

0n || 12n;
// ↪ 12n

0n && 12n;
// ↪ 0n

Boolean(0n);
// ↪ false

Boolean(12n);
// ↪ true

!12n;
// ↪ false

!0n;
// ↪ true
```

Конструктор
-----------

`BigInt()` (en-US)

Создаёт объект `BigInt`.

Статические методы
------------------

`BigInt.asIntN()`

Оборачивает BigInt в пределах от -2width-1 до 2width-1-1

`BigInt.asUintN()` (en-US)

Оборачивает a BigInt в пределах от 0 до 2width-1

Методы экземпляра
-----------------

`BigInt.prototype.toLocaleString()` (en-US)

Возвращает строку с языкозависимым представлением числа. Переопределяет метод `Object.prototype.toLocaleString()`.

`BigInt.prototype.toString()` (en-US)

Возвращает строку, представляющую указанный объект по указанному основанию системы счисления. Переопределяет метод `Object.prototype.toString()`.

`BigInt.prototype.valueOf()` (en-US)

Возвращает примитивное значение указанного объекта. Переопределяет метод `Object.prototype.valueOf()`.

Рекомендации по использованию
-----------------------------

### Приведение

Поскольку приведение между `Number` и `BigInt` может привести к потере точности, рекомендуется использовать `BigInt` только тогда, когда разумно ожидаются значения, превышающие 253 и не приводить между двумя типами.

### Криптография

Операции поддерживаемые `BigInt` не постоянны во времени. `BigInt` следовательно не пригоден для использования в криптографии.

### Использование вместе с JSON

Использование `JSON.stringify()` с любым значением типа `BigInt` приведёт к `TypeError`, поскольку значения `BigInt` не преобразуется в JSON по умолчанию, однако вы можете реализовать свой собственный метод `toJSON`, если вам необходимо:

```js
BigInt.prototype.toJSON = function () {
  return this.toString();
};
```

Теперь вместо ошибки, `JSON.stringify` будет создавать строку:

```js
JSON.stringify(BigInt(1));
// '"1"'
```

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

### Расчёт простых чисел

```js
// Возвращает true, если BigInt — простое число
function isPrime(p) {
  for (let i = 2n; i \* i <= p; i++) {
    if (p % i === 0n) return false;
  }
  return true;
}

// Берет BigInt в качестве аргумента и возвращает BigInt
function nthPrime(nth) {
  let maybePrime = 2n;
  let prime = 0n;

  while (nth >= 0n) {
    if (isPrime(maybePrime)) {
      nth--;
      prime = maybePrime;
    }
    maybePrime++;
  }

  return prime;
}

nthPrime(20n);
// ↪ 73n
```

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

| Specification |
| --- |
| ECMAScript Language Specification # sec-bigint-objects |

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

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

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

* `Number`
* `Number.MAX_SAFE_INTEGER`