Console.count() - Интерфейсы веб API

Console.count()
===============

Выводит число, равное тому, сколько раз была вызвана конкретная функция `count()`. Эта функция также принимает необязательный аргумент `label`.
**Примечание:** Эта возможность доступна в Web Workers

Если `label` передаётся в функцию, то она выводит число вызовов функции `count()` с такой же точно `label`.

Если `label` опущена, то функция выводит такое число, сколько раз была вызвана функция `count()` в этой отдельной строке.

Например, при таком коде:

```js
var user = "";

function greet() {
  console.count();
  return "hi " + user;
}

user = "bob";
greet();
user = "alice";
greet();
greet();
console.count();
```

В консоль выведется:
```

"<no label>: 1"
"<no label>: 2"
"<no label>: 3"
"<no label>: 1"
```

Обратите внимание на итоговую строку вывода журнала: отдельный вызов count () в строке 11 рассматривается как независимое событие.

Если мы передадим переменную `user` в качестве аргумента `label` при первом вызове функции `count()`, и строку "alice" при втором:

```js
var user = "";

function greet() {
  console.count(user);
  return "hi " + user;
}

user = "bob";
greet();
user = "alice";
greet();
greet();
console.count("alice");
```

На выходе мы увидим:
```

"bob: 1"
"alice: 1"
"alice: 2"
"alice: 3"
```

Таким образом мы сохранили различные счётчики основываясь только на значении `label`. Поскольку строка "alice" в строке 11 совпала со значением `user` дважды, это не сочлось отдельным событием.

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

console.count([label]);
```

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

`label`

Строка. Если она передаётся, `count()` выводит такое число, которое соответствует количеству раз вызова данной функции с таким же точно `label`.

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

| Specification |
| --- |
| Console Standard # count |

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

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


console.assert() - Интерфейсы веб API

console.assert()
================

**Не стандартно:** Эта возможность не является стандартной и стандартизировать её пока никто не собирается. Не используйте её на сайтах, смотрящих во внешний мир: она будет работать не у всех пользователей. Также могут присутствовать большие несовместимости между реализациями и её поведение может в будущем измениться.

Метод **`console.assert()`** записывает сообщение об ошибке в консоль в случае, если утверждение ложно. Если утверждение истинно - ничего не происходит.

**Примечание:** Эта возможность доступна в Web Workers

**Примечание:** Реализация м*етода `console.assert()` в браузере и Node.js отличается.*

В браузере, вызов console.assert() с ложным утверждением вызовет печать ошибки в консоль без прерывания текущего выполнения скрипта, а в Node.js в аналогичном случае будет выброшена ошибка - AssertionError.

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

console.assert(assertion, obj1 [, obj2, ..., objN]);
console.assert(assertion, msg [, subst1, ..., substN]); // си-подобное форматирование строк
```

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

`assertion`

Любое логическое утверждение. Если утверждение ложно - сообщение об ошибке записывается в консоль.

`obj1` ... `objN`

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

`msg`

Строка JavaScript, содержащая ноль или более строк подстановки.

`subst1` ... `substN`

Объекты JavaScript, которыми нужно заменить строки подстановки в рамках параметра **msg**. Этот параметр даёт дополнительный контроль над форматированием вывода.

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

В следующем примере кода демонстрируется использование объекта JavaScript после утверждения:

```js
const errorMsg = "# не чётное число";
for (let number = 2; number <= 5; number += 1) {
  console.log("# равно " + number);
  console.assert(number % 2 === 0, { number: number, errorMsg: errorMsg });
  // или, при использовании сокращения имён свойств в ECMAScript 2015:
  // console.assert(number % 2 === 0, {number, errorMsg});
}
// output:
// # равно 2
// # равно 3
// Assertion failed: {number: 3, errorMsg: "# не чётное число"}
// # равно 4
// # равно 5
// Assertion failed: {number: 5, errorMsg: "# не чётное число"}
```

Обратите внимание, что хотя строка, содержащая строку подстановки, работает как параметр для `console.log` в Node и многих, если не большинстве, браузерах...
```

console.log('слово %s', 'foo');
// output: слово foo
```

...использование такой строки в настоящее время не работает в качестве параметра для `console.assert` во всех браузерах:

```js
console.assert(false, "слово %s", "foo");
// корректный вывод в Node.js и некоторых браузерах
// (например Firefox v60.0.2):
// Assertion failed: слово foo
// некорректный вывод в некоторых браузерах
// (например Chrome v67.0.3396.87):
// Assertion failed: слово %s foo
```

Смотрите также Вывод текста в консоль в документации `console` для более детальной информации.

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

| Specification |
| --- |
| Console Standard # assert |

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

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

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

* Opera Dragonfly documentation: Console
* MSDN: Using the F12 Tools Console to View Errors and Status
* Chrome Developer Tools: Using the Console


Console.info() - Интерфейсы веб API

Console.info()
==============

Выводит сообщения, содержащие некоторую информацию, в Веб-консоль. В Firefox и Chrome, рядом с этими элементами в консоли отображается маленькая иконка "i".

**Примечание:** Эта возможность доступна в Web Workers

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

console.info(obj1 [, obj2, ..., objN]);
console.info(msg [, subst1, ..., substN]);
```

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

`obj1` ... `objN`

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

`msg`

Строка, содержащая 0 или более масок для замены.

`subst1` ... `substN`

Объекты JavaScript, которыми заменятся маски в строке `msg`. Так можно дополнительно контролировать формат вывода. Например, `console.info('Output %f', 234);` выведет в консоль: `Output 234.000000`

Смотрите Вывод текста в консоль в документации `console` для получения подробностей.

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

| Specification |
| --- |
| Console Standard # info |

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

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

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

* Opera Dragonfly documentation: Console
* MSDN: Using the F12 Tools Console to View Errors and Status


Console.warn() - Интерфейсы веб API

Console.warn()
==============

Выводит предупреждение в веб-консоль.
**Примечание:** Эта возможность доступна в Web Workers

**Примечание:** В Firefox, предупреждения имеют небольшое изображение восклицательного знака перед сообщением.

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

console.warn(obj1 [, obj2, ..., objN]);
console.warn(msg [, subst1, ..., substN]);
```

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

`obj1` ... `objN`

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

`msg`

Строка JavaScript, содержащая 0 и более подстановочных символов для замен.

`subst1` ... `substN`

JavaScript-объекты, с помощью которых произойдёт замена подстановочных символов в `msg`. Это даст вам дополнительный контроль над форматом вывода.

Больше подробностей смотрите в разделе Вывод текста в консоль документации `console`.

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

| Specification |
| --- |
| Console Standard # warn |

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

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

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

* Opera Dragonfly documentation: Console
* MSDN: Using the F12 Tools Console to View Errors and Status


console: статический метод dir() - Интерфейсы веб API

console: статический метод dir()
================================

Статический метод **`console.dir()`** отображает интерактивный список свойств указанного JavaScript объекта. Вывод представлен в виде иерархического списка с возможностью просмотра содержимого дочерних объектов.

Другими словами, `console.dir()` предоставляет возможность увидеть в консоли все свойства JavaScript объекта.

**Примечание:** Эта возможность доступна в Web Workers

![](/ru/docs/Web/API/console/dir_static/console-dir.png)

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

```js
dir(object)
```

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

`object`

JavaScript-объект, свойства которого нужно вывести.

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

Нет (`undefined`).

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

| Specification |
| --- |
| Console Standard # dir |

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

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

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

* Документация Microsoft Edge: `console.dir()`
* Документация Node.JS: `console.dir()`
* Документация Google Chrome: `console.dir()`


Console.dirxml() - Интерфейсы веб API

Console.dirxml()
================

Отображает интерактивное дерево из дочерних элементов указанного XML / HTML-элемента. Если невозможно отобразить как элемент, то вместо этого отображается представление объекта JavaScript. Выходные данные представлены в виде иерархического списка расширяемых узлов, которые позволяют вам видеть содержимое дочерних узлов.

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

console.dirxml(object);
```

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

`object`

Объект JavaScript свойства которого будут отображены.

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

| Specification |
| --- |
| Console Standard # dirxml |

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

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

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

* Opera Dragonfly documentation: Console


Console.timeStamp() - Интерфейсы веб API

Console.timeStamp()
===================

**Не стандартно:** Эта возможность не является стандартной и стандартизировать её пока никто не собирается. Не используйте её на сайтах, смотрящих во внешний мир: она будет работать не у всех пользователей. Также могут присутствовать большие несовместимости между реализациями и её поведение может в будущем измениться.

Добавляет маркер в браузерные инструменты Performance или Waterfall. Это помогает соотнести точку в вашем коде с другими записанными событиями.

**Примечание:** Эта возможность доступна в Web Workers

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

console.timeStamp(label);
```

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

`label`

Название метки. Необязательный параметр.

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

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

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

* `Console.time()`
* `Console.timeEnd()`
* Adding timestamps to the Waterfall


Console.time() - Интерфейсы веб API

Console.time()
==============

Запускает таймер, который вы можете использовать для определения, сколько времени занимает выполнение той или иной операции. Вы должны назначить каждому таймеру уникальное имя и таким образом можете запустить до 10000 таймеров на одной странице. Когда вы вызовете `console.timeEnd()` с именем, которое использовалось при запуске таймера, браузер отобразит в консоли время (в миллисекундах), прошедшее с момента запуска таймера.

Примеры и более детальная информация находятся в разделе Таймеры (en-US) документации к `console`

**Примечание:** Эта возможность доступна в Web Workers

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

console.time(label);
```

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

`label`

Название нового таймера. Оно однозначно идентифицирует таймер. Используйте то же самое название таймера, когда вызываете `console.timeEnd()` для остановки и отображения времени выполнения таймера.

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

| Specification |
| --- |
| Console Standard # time |

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

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

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

* `Console.timeEnd()`
* `Console.timeLog()`
* Opera Dragonfly documentation: Console


Console.log() - Интерфейсы веб API

Console.log()
=============

Выводит сообщение в веб-консоль.

**Примечание:** Эта возможность доступна в Web Workers

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

console.log(obj1 [, obj2, ..., objN]);
console.log(msg [, subst1, ..., substN]);
```

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

`obj1` ... `objN`

Список объектов JavaScript для вывода. Объекты выводятся в том порядке, в котором они были указаны при вызове метода. Пожалуйста, обратите внимание, что если вы логируете объекты в последних версиях Chrome и Firefox, в консоль залогируется не значение объекта, а *ссылка* на него. Это означает, что, возможно, в консоль будет выведено не значение объекта на момент вызова `console.log()`, а будет выведено значение объекта на момент открытия консоли.

`msg`

Строка JavaScript, содержащая 0 и более подстановочных символов для замены (см. `subst1` ... `substN`).

`subst1` ... `substN`

JavaScript-объекты, с помощью которых произойдёт замена подстановочных символов в `msg`. Это даст вам дополнительный контроль над форматом вывода.

Больше подробностей смотрите в разделе Вывод текста в консоль (en-US) документации `console`.

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

| Specification |
| --- |
| Console Standard # log |

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

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

Отличия от console.dir()
------------------------

Вы можете спросить какая разница между console.dir() и console.log(). Это полезное отличие.

![](http://i.imgur.com/DozDcYR.png)

Примечание:

* `console.log` выводит элемент как HTML-дерево
* `console.dir` выводит элемент как JSON-объект

А именно, `console.log` даёт специальное обращение к DOM-элементам, тогда как `console.dir` - нет. Это особенно полезно, когда нужно видеть полное представление DOM JS-объектов.

Больше информации об этой и других функциях в Chrome Console API reference.

Логирование объектов
--------------------

 Не используйте `console.log(obj);`,
 Используйте `console.log(JSON.parse(JSON.stringify(obj)));`.

Так вы можете быть уверены, что видите значение `obj` в момент, его логирования.

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

* Opera Dragonfly documentation: Console
* MSDN: Using the F12 Tools Console to View Errors and Status
* Firebug wiki: Console API - Firebug поддерживает дополнительные возможности реализации console.log(), такие как styled logging.
* NodeJS: Console API


Console.countReset() - Интерфейсы веб API

Console.countReset()
====================

Сбрасывает значение счётчика. Эта функция также принимает необязательный аргумент `label`.

**Примечание:** Эта возможность доступна в Web Workers

Если аргумент `label` передан, то функция сбросит счётчик связанный с этим аргументом.

Если значение `label` опущено, то функция сбросит счётчик, заданий по умолчанию.

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

console.countReset([label]);
```

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

`label`

 Строка.
 Если аргумент label был передан, `countReset()` сбросит к 0 счётчик для этого label.
 Если нет, `count()` сбросит к 0 счётчик, заданий по умолчанию.

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

Если аргумент label был передан:
```

 counter-name: 0
```

Если аргумент label не был определён:
```

default: 0
```

### Исключения

Если аргумент `label` был передан, но такого счётчика не существует `countReset` вернёт предупреждение:
```

Counter "counter-name" doesn’t exist.
```

Если аргумент `label` не был передан и `count()` не был вызван ранее, `countReset` вернёт предупреждение:
```

Counter "default" doesn’t exist.
```

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

Например, при таком коде:

```js
var user = "";

function greet() {
  console.count();
  return "hi " + user;
}

user = "bob";
greet();
user = "alice";
greet();
greet();
console.count();
console.countReset();
```

Вывод консоли будет примерно таким:
```

"default: 1"
"default: 2"
"default: 3"
"default: 1"
"default: 0"
```

Заметьте, что вызов console.counterReset() сбросил до 0 значение счётчика заданного по умолчанию.

Если мы присвоим переменную `user` как аргумент `label` при первом вызове `count()`, и строку "alice" при втором:

```js
var user = "";

function greet() {
  console.count(user);
  return "hi " + user;
}

user = "bob";
greet();
user = "alice";
greet();
greet();
console.countReset("bob");
console.count("alice");
```

Вывод будет примерно таким:
```

"bob: 1"
"alice: 1"
"alice: 2"
"bob: 0"
"alice: 3"
```

Сброс счётчика "bob" изменил значение только этого счётчика. Значение счётчика "alice" осталось неизменно.

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

| Specification |
| --- |
| Console Standard # countreset |

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

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


Event.type - Интерфейсы веб API

Event.type
==========

**`Event.type`** - это доступное только для чтения свойство, возвращающее строку, содержащую тип события. Оно устанавливается в момент создания события и это имя обычно используется для ссылки на определённое событие.

Аргумент *`event`* функций `EventTarget.addEventListener()` и `EventTarget.removeEventListener()` не чувствителен к регистру.

Для получения списка доступных типов событий смотри event reference

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

event.type
```

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

var string = event.type;
```

```
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">

    <title>Event.type Example</title>

    <script>
        var currEvent = null;

        function getEvtType(evt) {
            console.log("//Start------------getEvtType(evt)------------ ");

            currEvent = evt.type;
            console.log(currEvent);

            //document.getElementById("Etype").firstChild.nodeValue = currEvent;
            document.getElementById("Etype").innerHTML = currEvent;

            console.log("//End--------------getEvtType(evt)------------ ");
        }

        //Keyboard events
        document.addEventListener("keypress", getEvtType, false); //[second]

        document.addEventListener("keydown", getEvtType, false); //first
        document.addEventListener("keyup", getEvtType, false); //third

        //Mouse events
        document.addEventListener("click", getEvtType, false); // third

        document.addEventListener("mousedown", getEvtType, false); //first
        document.addEventListener("mouseup", getEvtType, false); //second

    </script>
</head>

<body>

    <p>Press any key or click the mouse to get the event type.</p>
    <p>Event type: <span id="Etype" style="color:red">-</span></p>

</body>
</html>
```

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-type④ |


Event.stopImmediatePropagation() - Интерфейсы веб API

Event.stopImmediatePropagation()
================================

Останавливает цепочку вызова событий для последующих обработчиков DOM-элемента.

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

event.stopImmediatePropagation();
```

Замечания
---------

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

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-stopimmediatepropagation① |

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

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


Event.bubbles - Интерфейсы веб API

Event.bubbles
=============

### Описание

Указывает, является ли данное событие всплывающим внутри DOM.

**Примечание:** Более подробно про всплытие событий: Всплытие и перехват событий

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

```js
event.bubbles;
```

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

### Значение

`bool` содержит `true` или `false` в зависимости от того, может событие быть всплывающим внутри DOM или нет

### Пример

```js
function handleInput(e) {
  // Проверяем всплывает ли событие и ...
  if (!e.bubbles) {
    // ... пропускаем событие сюда если нет
    passItOn(e);
  }

  // Уже всплыло
  doOutput(e);
}
```

**Примечание:** Только некоторые события могут всплывать. У таких событий это свойство возвращает `true`. Вы можете использовать это свойство, чтобы проверить, может ли событие всплывать.


Event.srcElement - Интерфейсы веб API

Event.srcElement
================

**Не стандартно:** Эта возможность не является стандартной и стандартизировать её пока никто не собирается. Не используйте её на сайтах, смотрящих во внешний мир: она будет работать не у всех пользователей. Также могут присутствовать большие несовместимости между реализациями и её поведение может в будущем измениться.

**`Event.srcElement`** это проприетарный синоним стандартного свойства `Event.target`. Специфичен для старых версий Microsoft Internet Explorer.

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

Не является частью каких-либо спецификаций.

Имеет описание от Microsoft на MSDN.

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

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

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

* `Window.event` (en-US)


Event.target - Интерфейсы веб API

Event.target
============

Свойство **`target`** интерфейса `Event` является ссылкой на объект, который был инициатором события. Он отличается от `Event.currentTarget`, если обработчик события вызывается во время всплытия (bubbling) или захвата события.

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

theTarget = event.target
```

Значение:

`EventTarget`Пример
------

Свойство `event.target` может быть использовано для реализации **делегирования событий**.
```

// Создадим список
var ul = document.createElement('ul');
document.body.appendChild(ul);

var li1 = document.createElement('li');
var li2 = document.createElement('li');
ul.appendChild(li1);
ul.appendChild(li2);

function hide(e){
  // e.target ссылается на кликнутый <li> элемент
  // Он отличается от e.currentTarget который будет ссылаться на родительский <ul> в этом контексте
  e.target.style.visibility = 'hidden';
}

// Назначим обработчик к списку
// Он будет вызван когда кликнут на любой <li>
ul.addEventListener('click', hide, false);
```

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-target③ |

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

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

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

* Comparison of Event Targets


Event() - Интерфейсы веб API

Event()
=======

Конструктор **`Event()`** создаёт новый объект события `Event`.

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

 event = new Event(typeArg, eventInit);
```

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

*typeArg*

Строковое (`DOMString`) значение, представляющее имя события.

*eventInit* Необязательный

Is an `EventInit` dictionary, having the following fields:

* `"bubbles"`: (Необязательный) логическое значение (`Boolean`) указывающее – будет ли событие всплывающим. По умолчанию `false`.
* `"cancelable"`: (Необязательный) логическое значение (`Boolean`) указывает, может ли событие быть отменено. По умолчанию `false`.
* `"composed"`: (Необязательный) логическое значение `Boolean` указывающее – будет ли событие всплывать наружу за пределы shadow root. По умолчанию `false`.

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

```js
// создать событие "look", событие всплывающее и не может быть отменено

var evt = new Event("look", { bubbles: true, cancelable: false });
document.dispatchEvent(evt);

// событие может быть инициализировано на любом элементе, а не только на документе
myDiv.dispatchEvent(evt);
```

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-event |

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

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

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

* `Event`


Event.eventPhase - Интерфейсы веб API

Event.eventPhase
================

### Общая информация

Отображает текущую фазу процесса обработки события.

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

var phase = event.eventPhase;
```

Возвращает целое число, соответствующее одной из 4 констант:

* `Event.NONE = 0`
* `Event.CAPTURING_PHASE = 1`
* `Event.AT_TARGET = 2`
* `Event.BUBBLING_PHASE = 3`

Смысл констант смотри в section 3.1, Event dispatch and DOM event flow, спецификации DOM Level 3.

### Пример
```

<!DOCTYPE html>
<html>
<head> <title>Event Propagation</title>
  <style type="text/css">
    body { font-family:'Trebuchet MS'; }
    div { margin: 20px; padding: 4px; border: thin black solid; }
    #divInfo { margin: 18px; padding: 8px; background-color:white; font-size:80%; }
  </style>
</head>
<body>
  <h4>Event Propagation Chain</h4>
  <ul>
    <li>Click 'd1'</li>
    <li>Analyse event propagation chain</li>
    <li>Click next div and repeat the experience</li>
    <li>Change Capturing mode</li>
    <li>Repeat the experience</li>
  </ul>
  <input type="checkbox" id="chCapture" /> Use Capturing
  <div id="d1">d1
    <div id="d2">d2
      <div id="d3">d3
        <div id="d4">d4</div>
      </div>
    </div>
  </div>
  <div id="divInfo"></div>
  <script>
    var
      clear = false,
      divInfo = null,
      divs = null,
      useCapture = false;
  window.onload = function ()
  {
    divInfo = document.getElementById("divInfo");
    divs = document.getElementsByTagName('div');
    chCapture = document.getElementById("chCapture");
    chCapture.onclick = function ()
    {
      RemoveListeners();
      AddListeners();
    }
    Clear();
    AddListeners();
  }
  function RemoveListeners()
  {
    for (var i = 0; i < divs.length; i++)
    {
      var d = divs[i];
      if (d.id != "divInfo")
      {
        d.removeEventListener("click", OnDivClick, true);
        d.removeEventListener("click", OnDivClick, false);
      }
    }
  }
  function AddListeners()
  {
    for (var i = 0; i < divs.length; i++)
    {
      var d = divs[i];
      if (d.id != "divInfo")
      {
        d.addEventListener("click", OnDivClick, false);
        if (chCapture.checked)
          d.addEventListener("click", OnDivClick, true);
        d.onmousemove = function () { clear = true; };
      }
    }
  }
  function OnDivClick(e)
  {
    if (clear)
    {
      Clear();
      clear = false;
    }

    if (e.eventPhase == 2)
      e.currentTarget.style.backgroundColor = 'red';

    var level =
        e.eventPhase == 0 ? "none" :
        e.eventPhase == 1 ? "capturing" :
        e.eventPhase == 2 ? "target" :
        e.eventPhase == 3 ? "bubbling" : "error";
    divInfo.innerHTML += e.currentTarget.id + "; eventPhase: " + level + "<br/>";
  }
  function Clear()
  {
    for (var i = 0; i < divs.length; i++)
    {
      if (divs[i].id != "divInfo")
        divs[i].style.backgroundColor = (i & 1) ? "#f6eedb" : "#cceeff";
    }
    divInfo.innerHTML = '';
  }
  </script>
</body>
</html>
```

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

DOM Level 2 Events: Event.eventPhase


Event.cancelable - Интерфейсы веб API

Event.cancelable
================

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

Указывает, является ли событие отменяемым.

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

bool = event.cancelable
```

* Возвращает булево значение `true`, если событие может быть отменено.
Пример
------

```js
var bool = event.cancelable;
```

`bool` содержит `true` или `false` в зависимости от того, можно ли предотвратить действие события по умолчанию или нет.

Примечание
----------

Независимо от того, может событие быть отменено или нет, свойство определяется при инициализации события.

Вызов на событии метода `preventDefault()` отменяет событие. При этом действие по умолчанию, связанное с событием, не выполняется.

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-cancelable② |

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

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


Event.preventDefault() - Интерфейсы веб API

Event.preventDefault()
======================

Метод preventDefault () интерфейса `Event` сообщает User agent, что если событие не обрабатывается явно, его действие по умолчанию не должно выполняться так, как обычно. Событие продолжает распространяться как обычно, до тех пор, пока один из его обработчиков не вызывает методы  `stopPropagation ()` или  `stopImmediatePropagation ()`, любой из которых сразу же прекращает распространение.Как отмечено ниже, вызов метода preventDefault () для события, не подлежащего отмене, например события, отправленного через `EventTarget.dispatchEvent ()`, без указания cancelable: true не имеет эффекта.Синтаксис
---------
```

event.preventDefault();
```

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

По умолчанию щелчок по флажку переключает его состояние на противоположное. В этом примере показано, как предотвратить такое поведение:

```html
<!doctype html>
<html>
  <head>
    <title>Пример preventDefault</title>

    <script>
 function stopDefAction(evt) {
 evt.preventDefault();
 }

 document
 .getElementById("my-checkbox")
 .addEventListener("click", stopDefAction, false);
 </script>
  </head>

  <body>
    <p>Пожалуйста, щёлкните по флажку.</p>

    <form>
      <input type="checkbox" id="my-checkbox" />
      <label for="my-checkbox">Checkbox</label>
    </form>
  </body>
</html>
```

Вы можете посмотреть работу `preventDefault` в действии здесь.

В следующем примере некорректный ввод останавливается и вводимый символ не добавляется в поле с `preventDefault()`.

```html
<!DOCTYPE html>
<html>
<head>
<title>Пример preventDefault</title>

<script>
```

```js
function Init() {
  var myTextbox = document.getElementById("my-textbox");
  myTextbox.addEventListener("keypress", checkName, false);
}

function checkName(evt) {
  var charCode = evt.charCode;
  if (charCode != 0) {
    if (charCode < 97 || charCode > 122) {
      evt.preventDefault();
      alert(
        "Пожалуйста, используйте только буквы нижнего регистра на латинице" +
          "\n" +
          "charCode: " +
          charCode +
          "\n",
      );
    }
  }
}
```

```html
</script>
</head>
<body onload="Init ()">
    <p>Пожалуйста, введите своё имя, используя только буквы нижнего регистра на латинице.</p>
    <form>
        <input type="text" id="my-textbox" />
    </form>
</body>
</html>
```

Результат выполнения кода:

Примечания
----------

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

**Примечание:** В Gecko 6.0, вызов `preventDefault()` приводит к `event.defaultPrevented` к переходу значения в состояние `True`.

Вы можете использовать event.cancelable (en-US) чтобы проверить, является ли событие отменяемым. Вызов `preventDefault` для неотменяемых событий не имеет никакого эффекта.

`preventDefault` не останавливает дальнейшее распространение событий на DOM. Для этого следует использовать event.stopPropagation (en-US).

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-preventdefault③ |

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

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


Event.isTrusted - Интерфейсы веб API

Event.isTrusted
===============

`isTrusted` - свойство объекта `Event`, доступное только на чтение. Принимает значение true, если событие было инициировано действиями пользователя, и false, если событие было создано или изменено скриптом, либо с помощью dispatchEvent

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

var bool = event.isTrusted;
```

Пример
------
```

 if (e.isTrusted) {
     /* The event is trusted. */
 } else {
     /* The event is not trusted. */
 }
```

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-istrusted① |

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

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


Event.timeStamp - Интерфейсы веб API

Event.timeStamp
===============

Возвращает время (в миллисекундах), в котором было создано событие.

>
> \*\*Примечание:\*\*Это свойство работает только в том случае, если система событий поддерживает его для конкретного события.
>
>
>

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

event.timeStamp
```

### Значение

Значение - это миллисекунды, прошедшие с начала жизненного цикла текущего документа до создания события.

In newer implementations, the value is a `DOMHighResTimeStamp` accurate to 5 microseconds (0.005 ms). In older implementations, the value is a `DOMTimeStamp` (en-US), accurate to a millisecond.

Example
-------

### HTML content

```html
<p>
  Focus this iframe and press any key to get the current timestamp for the
  keypress event.
</p>
<p>timeStamp: <span id="time">-</span></p>
```

### JavaScript content

```js
function getTime(event) {
  var time = document.getElementById("time");
  time.firstChild.nodeValue = event.timeStamp;
}
document.body.addEventListener("keypress", getTime);
```

### Result

Reduced time precision
----------------------

 To offer protection against timing attacks and fingerprinting, the precision of `event.timeStamp` might get rounded depending on browser settings.
 In Firefox, the `privacy.reduceTimerPrecision` preference is enabled by default and defaults to 20us in Firefox 59; in 60 it will be 2ms.

```js
// reduced time precision (2ms) in Firefox 60
event.timeStamp;
// 1519211809934
// 1519211810362
// 1519211811670
// ...

// reduced time precision with `privacy.resistFingerprinting` enabled
event.timeStamp;
// 1519129853500
// 1519129858900
// 1519129864400
// ...
```

In Firefox, you can also enabled `privacy.resistFingerprinting`, the precision will be 100ms or the value of `privacy.resistFingerprinting.reduceTimerPrecision.microseconds`, whichever is larger.

Specifications
--------------

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-timestamp① |

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

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


Event.initEvent() - Интерфейсы веб API

Event.initEvent()
=================

**Устарело:** Эта возможность была удалена из веб-стандартов. Хотя некоторые браузеры по-прежнему могут поддерживать её, она находится в процессе удаления. Не используйте её ни в старых, ни в новых проектах. Страницы или веб-приложения, использующие её, могут в любой момент сломаться.

The **`Event.initEvent()`** method is used to initialize the value of an `event` created using `Document.createEvent()` (en-US).

Events initialized in this way must have been created with the `Document.createEvent()` (en-US) method. This method must be called to set the event before it is dispatched, using `EventTarget.dispatchEvent()`. Once dispatched, it doesn't do anything anymore.

**Примечание:** Не используйте этот метод, т.к. он устаревший. (deprecated)

Вместо него используйте такой специальный конструктор событий, как `Event()`. Страница Creating and triggering events (en-US) даст больше информации о возможностях использования.

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

event.initEvent(type, bubbles, cancelable);
```

`type`

`DOMString`, определяющая тип события.

`bubbles`

Is a `Boolean` deciding whether the event should bubble up through the event chain or not. Once set, the read-only property `Event.bubbles` will give its value.

`cancelable`

Is a `Boolean` defining whether the event can be canceled. Once set, the read-only property `Event.cancelable` will give its value.

Пример
------
```

// Create the event.
var event = document.createEvent('Event');

// Create a click event that bubbles up and
// cannot be canceled
event.initEvent('click', true, false);

// Listen for the event.
elem.addEventListener('click', function (e) {
  // e.target matches elem
}, false);

elem.dispatchEvent(event);
```

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-initevent① |

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

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

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

* The constructor to use instead of this deprecated method: `Event()`. More specific constructors can be used too.


Сравнение разных Event Targets - Интерфейсы веб API

Сравнение разных Event Targets
==============================

### Event targets

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

Существуют 5 целей для рассмотрения:

| Property | Defined in | Purpose |
| --- | --- | --- |
| event.target | DOM Event Interface | Элемент DOM слева от вызова этого события, например:
```

*element*.dispatchEvent(*event*)
```

 |
| event.currentTarget | DOM Event Interface | `EventTarget`, чьи
 `EventListeners`
 в настоящее время обрабатываются. По мере того, как происходит захват и
 всплытие событий, это значение изменяется.
  |
| event.relatedTarget (en-US) | DOM MouseEvent Interface | Определяет вторичную цель для события. |
| event.explicitOriginalTarget (en-US) | Event.webidl |
Non-standard
 Если по какой-либо причине событие
 было перенацелено, кроме анонимного пересечения границ, событие будет
 установлено на цель до перенацеливания. Например, события мыши
 перенацеливаются на их родительский узел, когда они встречаются над
 текстовыми узлами ([Firefox bug 185889](https://bugzil.la/185889)), и в этом случае
 `.target` покажет на родителя и
 `.explicitOriginalTarget` покажет на текстовый узел.В
 отличие от `.originalTarget` —
 `.explicitOriginalTarget` никогда не будет содержать
 анонимный контент.
  |
| event.originalTarget (en-US) | Event.webidl |
Non-standard
 Первоначальная цель события перед
 любым перенацеливанием. Подробнее см.
 Анонимный контент#Event\_Flow\_and\_Targeting.
  |

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

>
> **Note:** These properties are only available in Mozilla-based browsers.
>
>
>

### Примеры

```html
<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <title>Comparison of Event Targets</title>
    <style>
 table {
 border-collapse: collapse;
 height: 150px;
 width: 100%;
 }
 td {
 border: 1px solid #ccc;
 font-weight: bold;
 padding: 5px;
 min-height: 30px;
 }
 .standard {
 background-color: #99ff99;
 }
 .non-standard {
 background-color: #902d37;
 }
 </style>
  </head>
  <body>
    <table>
      <thead>
        <tr>
          <td class="standard">
            Изначальная цель, отправляющая событие <small>event.target</small>
          </td>
          <td class="standard">
            Цель, кто обрабатывает события <small>event.currentTarget</small>
          </td>
          <td class="standard">
            Идентифицировать другой элемент (если он есть), участвующий в
            событии <small>event.relatedTarget</small>
          </td>
          <td class="non-standard">
            Если по какой-то причине произошло перенацеливание события
            <small>event.explicitOriginalTarget</small> содержит цель перед
            перенацеливанием (никогда не содержит анонимных целей)
          </td>
          <td class="non-standard">
            Если по какой-то причине произошло перенацеливание события
            <small>event.originalTarget</small> содержит цель перед
            перенацеливанием (может содержать анонимные цели)
          </td>
        </tr>
      </thead>
      <tr>
        <td id="target"></td>
        <td id="currentTarget"></td>
        <td id="relatedTarget"></td>
        <td id="explicitOriginalTarget"></td>
        <td id="originalTarget"></td>
      </tr>
    </table>
    <p>
      Нажав на текст, вы увидите разницу между explicitOriginalTarget,
      originalTarget и target
    </p>
    <script>
 function handleClicks(e) {
 document.getElementById("target").innerHTML = e.target;
 document.getElementById("currentTarget").innerHTML = e.currentTarget;
 document.getElementById("relatedTarget").innerHTML = e.relatedTarget;
 document.getElementById("explicitOriginalTarget").innerHTML =
 e.explicitOriginalTarget;
 document.getElementById("originalTarget").innerHTML = e.originalTarget;
 }

 function handleMouseover(e) {
 document.getElementById("target").innerHTML = e.target;
 document.getElementById("relatedTarget").innerHTML = e.relatedTarget;
 }

 document.addEventListener("click", handleClicks, false);
 document.addEventListener("mouseover", handleMouseover, false);
 </script>
  </body>
</html>
```

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

Свойство `relatedTarget` для события `mouseover` содержит узел, над которым ранее была указана мышь. Для события `mouseout` он удерживает узел, к которому движется мышь.

| Тип события | event.target | event.relatedTarget (en-US) |
| --- | --- | --- |
| `mouseover` | EventTarget, в который входим указателем | EventTarget, из которого выходим указателем |
| `mouseout` | EventTarget, из которого выходим указателем | EventTarget, в который входим указателем |

TODO: Также требуется описание событий `dragenter` и `dragexit`.

#### Пример

```xml
<hbox id="outer">
  <hbox id="inner"
 onmouseover="dump('mouseover ' + event.relatedTarget.id + ' > ' + event.target.id + '\n');"
 onmouseout="dump('mouseout ' + event.target.id + ' > ' + event.relatedTarget.id + '\n');"
 style="margin: 100px; border: 10px solid black; width: 100px; height: 100px;" />
</hbox>
```


Event.currentTarget - Интерфейсы веб API

Event.currentTarget
===================

Определяет элемент, в котором в данный момент обрабатывается событие, при движении события внутри DOM. Всегда совпадает элементом, на котором обработчик события был назначен, в отличие от свойства `event.target`, идентифицирующего элемент, на котором событие возникло.

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

`event.currentTarget` используется, когда один и тот же обработчик события присваивается нескольким элементам.

```js
function hide(e) {
  e.currentTarget.style.visibility = "hidden";
  // Когда данная функция используется в качестве обработчика события: this === e.currentTarget
}

var ps = document.getElementsByTagName("p");

for (var i = 0; i < ps.length; i++) {
  ps[i].addEventListener("click", hide, false);
}

// click around and make paragraphs disappear
```

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-currenttarget② |

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

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

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

Comparison of Event Targets


Event.stopPropagation() - Интерфейсы веб API

Event.stopPropagation()
=======================

Прекращает дальнейшую передачу текущего события.

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

event.stopPropagation();
```

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

См. Пример 5: Event Propagation для более детального объяснения данного метода и всего механизма передачи событий в DOM документе.

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-stoppropagation① |

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

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

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

* Смотрите DOM specification для понимания потока событий. (DOM Level 3 Events draft содержит иллюстрации.)
* `Event.preventDefault()` – это дополнительный метод, который запрещает исполнение метода по умолчанию, предназначенного для данного события.


Event.defaultPrevented - Интерфейсы веб API

Event.defaultPrevented
======================

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

Возвращает boolean-значение, информирующее о том, был ли вызван `event.preventDefault()` в текущем обработчике события.

**Примечание:** Используйте это свойство вместо `устаревшего метода getPreventDefault()` (смотри Firefox bug 691151).

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

```js
var defaultWasPrevented = event.defaultPrevented;
```

Пример
------
```

 if (e.defaultPrevented) {
   /* по умолчанию не выполнится */
 }
```

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-defaultprevented① |

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

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


Gamepad.index - Интерфейсы веб API

Gamepad.index
=============

Свойство **`Gamepad.index`** интерфейса `Gamepad` возвращает целое автоинкрементируемое значение, уникальное для каждого устройства, подключённого к системе.

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

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

readonly    attribute long                index;
```

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

```js
window.addEventListener("gamepadconnected", function () {
  var gp = navigator.getGamepads()[0];
  gamepadInfo.innerHTML =
    "Gamepad connected at index " + gp.index + ": " + gp.id + ".";
});
```

### Значение

`Number`.

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

| Specification |
| --- |
| Gamepad # dom-gamepad-index |

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

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

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

Using the Gamepad API (en-US)


Gamepad.axes - Интерфейсы веб API

Gamepad.axes
============

Свойство **`Gamepad.axes`** интерфейса `Gamepad` возвращает массив, показывающий состояние элементов управления, имеющих оси направления, такие как джойстики на геймпаде.

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

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

readonly    attribute double[]            axes;
```

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

```js
function gameLoop() {
  if (navigator.webkitGetGamepads) {
    var gp = navigator.webkitGetGamepads()[0];
  } else {
    var gp = navigator.getGamepads()[0];
  }

  if (gp.axes[0] != 0) {
    b -= gp.axes[0];
  } else if (gp.axes[1] != 0) {
    a += gp.axes[1];
  } else if (gp.axes[2] != 0) {
    b += gp.axes[2];
  } else if (gp.axes[3] != 0) {
    a -= gp.axes[3];
  }

  ball.style.left = a \* 2 + "px";
  ball.style.top = b \* 2 + "px";

  var start = rAF(gameLoop);
}
```

Значение
--------

Массив значений `double`

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

| Specification |
| --- |
| Gamepad # dom-gamepad-axes |

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

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

See also
--------

Using the Gamepad API (en-US)


Gamepad.buttons - Интерфейсы веб API

Gamepad.buttons
===============

Свойство **`Gamepad.buttons`** интерфейса `Gamepad` возвращает массив, состоящий из объектов `gamepadButton`, представляющие кнопки, представленные на устройстве (геймпаде).

Каждый элемент в массиве равен 0 если кнопка не нажата, и не-нуль (обычно 1.0) если нажата. Каждый объект `gamepadButton` содержит два параметра: `pressed` и `value`:

* Свойство `pressed` - boolean индикатор, показывающий, нажата ли кнопка (`true`) или нет (`false`).
* Свойство `value` - число с плавающей точкой, показывающая степень нажатия на аналоговую кнопку (как триггеры на многих современных геймпадах). Значение нормализованное в диапазоне 0.0 – 1.0, где 0.0 указывает, что кнопка не нажата, а 1.0 - что нажата полностью.
Синтаксис
---------
```

readonly    attribute GamepadButton[]     buttons;
```

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

Приведённый код взят из моего *(автора статьи)* демо Gamepad API button (вы можете Посмотреть демо, и посмотреть исходники на GitHub). Важно — в Chrome `Navigator.getGamepads` необходимо установить префикс `webkit`, и значения кнопки будут представлять из себя массив дробных чисел, тогда как в Firefox `Navigator.getGamepads` нет необходимости устанавливать префикс, и значения будут представлять собой массив объектов `GamepadButton`; Свойство `GamepadButton.value` или `GamepadButton.pressed` необходимо для получения состояния кнопки, в зависимости от от типа кнопки. В данном простом примере обрабатывается оба вида кнопок.

```js
function gameLoop() {
  if (navigator.webkitGetGamepads) {
    var gp = navigator.webkitGetGamepads()[0];

    if (gp.buttons[0] == 1) {
      b--;
    } else if (gp.buttons[1] == 1) {
      a++;
    } else if (gp.buttons[2] == 1) {
      b++;
    } else if (gp.buttons[3] == 1) {
      a--;
    }
  } else {
    var gp = navigator.getGamepads()[0];

    if (gp.buttons[0].value > 0 || gp.buttons[0].pressed == true) {
      b--;
    } else if (gp.buttons[1].value > 0 || gp.buttons[1].pressed == true) {
      a++;
    } else if (gp.buttons[2].value > 0 || gp.buttons[2].pressed == true) {
      b++;
    } else if (gp.buttons[3].value > 0 || gp.buttons[3].pressed == true) {
      a--;
    }
  }

  ball.style.left = a \* 2 + "px";
  ball.style.top = b \* 2 + "px";

  var start = window.requestAnimationFrame(gameLoop);
}
```

Значение
--------

Массив из объектов `gamepadButton`

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

| Specification |
| --- |
| Gamepad # dom-gamepad-buttons |

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

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

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

Using the Gamepad API (en-US)


Gamepad.connected - Интерфейсы веб API

Gamepad.connected
=================

Свойство **`Gamepad.connected`** интерфейса `Gamepad` возвращает логическое значение того, подключён ли всё ещё геймпад к системе.

Если геймпад подключён - значение равно `true`; если нет - `false`.

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

 readonly    attribute boolean             connected;
```

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

```js
var gp = navigator.getGamepads()[0];
console.log(gp.connected);
```

Значение
--------

`Boolean`.

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

| Specification |
| --- |
| Gamepad # dom-gamepad-connected |

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

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

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

Using the Gamepad API (en-US)


Gamepad.timestamp - Интерфейсы веб API

Gamepad.timestamp
=================

Свойство **`Gamepad.timestamp`** интерфейса `Gamepad` возвращает `DOMHighResTimeStamp`, представляющий собой время последнего обновления геймпада.

Идея состоит в том, чтобы позволить разработчику определить, были ли изменены данные для `axes` и `button` на аппаратном обеспечении. Значение должно быть установлено относительно атрибута `navigationStart` интерфейса ``PerformanceTiming` (en-US)`. Значения монотонно увеличиваются, поэтому их можно сравнивать, чтобы определить порядок изменений, т.к. новые значения всегда будут больше или равны старым.

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

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

readonly    attribute DOMHighResTimeStamp timestamp;
```

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

```js
var gp = navigator.getGamepads()[0];
console.log(gp.timestamp);
```

Значение
--------

`DOMHighResTimeStamp`.

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

| Specification |
| --- |
| Gamepad # dom-gamepad-timestamp |

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

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

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

Using the Gamepad API (en-US)


Gamepad.mapping - Интерфейсы веб API

Gamepad.mapping
===============

Свойство **`Gamepad.mapping`** интерфейса `Gamepad` возвращает строковый индикатор, указывающий, изменил ли браузер элементы управления на уже известный шаблон

На данный момент существует один поддерживаемый шаблон - standard gamepad. Если браузер позволяет поменять элементы управления в данном шаблоне, свойство `mapping` будет установлено строка `"standard"`.

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

readonly    attribute DOMString           mapping;
```

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

```js
var gp = navigator.getGamepads()[0];
console.log(gp.mapping);
```

Значение
--------

A `string`.

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

| Specification |
| --- |
| Gamepad # dom-gamepad-mapping |

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

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

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

Using the Gamepad API (en-US)


Gamepad.id - Интерфейсы веб API

Gamepad.id
==========

Свойство **`Gamepad.id`** интерфейса `Gamepad` возвращает строку, содержащую некоторую информацию о контроллере.

Существующий синтаксис не стандартизирован, но в Firefox эта строка представляет собой три значения, разделённые тире (`-`):

* Две четырёхзначных шестнадцатеричных строки, содержащих USB vendor id (`VID`) и product id (`PID`) контроллера
* Имя контроллера, предоставленное драйвером.

Например, PS2 контроллер вернёт **`810-3-USB Gamepad`**.

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

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

readonly    attribute DOMString           id;
```

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

```js
window.addEventListener("gamepadconnected", function () {
  var gp = navigator.getGamepads()[0];
  gamepadInfo.innerHTML =
    "Gamepad connected at index " + gp.index + ": " + gp.id + ".";
});
```

Значение
--------

`String`.

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

| Specification |
| --- |
| Gamepad # dom-gamepad-id |

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

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

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

Using the Gamepad API (en-US)


Gamepad.displayId - Интерфейсы веб API

Gamepad.displayId
=================

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

Свойство **displayId** только для чтения `Gamepad` возвращаемый интерфейс\* `VRDisplay.displayId` (en-US) связанный с `VRDisplay` (en-US) — `VRDisplay` (дисплей виртуальной реальности) в котором геймпад управляет отображаемой сценой.\*

Геймпад считается связанным с `VRDisplay` (en-US) если он сообщает о позиции, которая находится в том же месте, что и `VRDisplay.pose`.

Syntax
------

```js
var myDisplayId = gamepadInstance.displayId;
```

### Value

Число, представляющее связанный интерфейс `VRDisplay.displayId` (en-US).Если число равно 0, то геймпад не связан с дисплеем VR( виртуальной реальности).

Examples
--------

```js
window.addEventListener("gamepadconnected", function (e) {
  if (!e.gamepad.displayId) {
    console.log("Gamepad connected");
  } else {
    console.log(
      "Gamepad connected, associated with VR display " + e.gamepad.displayId,
    );
  }
});
```

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

#### No specification found

No specification data found for `api.Gamepad.displayId`.
Check for problems with this page or contribute a missing `spec_url` to mdn/browser-compat-data. Also make sure the specification is included in w3c/browser-specs.

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

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

See also
--------

* WebVR API


Перевод из текстового формата WebAssembly в Wasm - WebAssembly

Перевод из текстового формата WebAssembly в Wasm
================================================

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

**Примечание:** Файлы текстового формата обычно сохраняются с расширением `.wat`. Исторически так же использовалось расширение `.wast`, однако, теперь оно применяется для языка сценариев, используемого тестами WebAssembly.

Пример текстового формата
-------------------------

Давайте рассмотрим простой пример: следующая программа импортирует функцию с именем `imported_func` из модуля с именем `imports` и экспортирует функцию с именем `exported_func`:

```wasm
(module
  (func $i (import "imports" "imported\_func") (param i32))
  (func (export "exported\_func")
    i32.const 42
    call $i
  )
)
```

Функция `exported_func` экспортируется для использования в нашей среде (например, web-приложении, в котором мы используем наш модуль WebAssembly). Когда он вызывается, он вызывает импортированную функцию JavaScript с именем `imported_func`, которая запускается со значением (42), передаваемым в качестве параметра.

Преобразование текстового формата .wat в двоичный .wasm файл
------------------------------------------------------------

Давайте попробуем преобразовать приведенный выше пример текстового представления `.wat` в двоичный формат `.wasm`.

1. Для начала сделайте копию приведенного выше примера в текстовом файле. Назовите его `simple.wat`.
2. Нам нужно преобразовать это текстовое представление в двоичный формат, который фактически читает браузер, прежде чем мы сможем его использовать. Для этого мы можем использовать инструментарий wabt, который включает в себя компиляторы для преобразования между текстовым представлением WebAssembly и wasm и наоборот, а также многие другие утилиты. Перейдите по адресу https://github.com/webassembly/wabt — следуйте инструкциям на этой странице, чтобы настроить инструментарий.
3. Если вы собираете утилиты wabt из исходного кода, добавьте каталог `/wabt/out/clang/Debug` в переменную `PATH`.
4. Затем запустите программу wat2wasm, передав ей путь к исходному файлу, за которым следует параметр `-o`, а затем путь к выходному файлу:

```bash
wat2wasm simple.wat -o simple.wasm
```

Это преобразует исходный текстовый код в файл с именем `simple.wasm`, который содержит собранный двоичный код `.wasm`.

**Примечание:** Вы также можете преобразовать сборку обратно в текстовое представление при помощи утилиты wasm2wat, например, `wasm2wat simple.wasm -o text.wat`.

Просмотр файлов сборки
----------------------

Поскольку выходной файл является двоичным форматом сборки, его нельзя просмотреть в обычном текстовом редакторе. Однако, вы можете просмотреть его, используя параметр `-v` утилиты wat2wasm. Попробуйте выполнить следующую команду:

```bash
wat2wasm simple.wat -v
```

Она выдаст информацию в терминале следующим образом:

![несколько строк двоичного кода с текстовым описанием рядом с ними. Например: 0000008: 01 ; section code ](/ru/docs/WebAssembly/Text_format_to_Wasm/assembly-output.png)

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

* Описание текстового формата WebAssembly — подробное объяснение синтаксиса текстового формата.
* Компиляция кода C/C++ в WebAssembly — описание инструментов Binaryen/Emscripten, которые компилируют ваш исходный код в wasm и создают код API, необходимый для запуска модуля в контексте JavaScript. Узнайте больше о том, как их использовать.
* Использование WebAssembly JavaScript API — прочтите это, если хотите узнать больше о том, как работает код WebAssembly API.
* Описание текстового формата — детальная спецификация текстового формата WebAssembly в GitHub репозитории.
* wast-loader — загрузчик текстового формата WebAssembly для webpack.


Компиляция кода C/C++ в WebAssembly - WebAssembly

Компиляция кода C/C++ в WebAssembly
===================================

После того как вы написали код на C / C ++, вы можете скомпилировать его в WebAssembly, например, с помощью инструмента Emscripten. Давайте посмотрим, как это работает.

Подготовка рабочей среды для Emscripten
---------------------------------------

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

### Необходимые компоненты

Установите Emscripten SDK и настройте рабочее окружение используя инструкции: https://kripken.github.io/emscripten-site/docs/getting\_started/downloads.html

Компиляция примера
------------------

Когда рабочее окружение подготовлено, попробуем собрать пример кода на языке Си при помощи Emscripten. Вам доступно большое количество опций для настройки компиляции, но мы рассмотрим только два основных сценария компиляции с использованием Emscripten:

* Компиляция в wasm и создание HTML-страницы для запуска вашего кода, а также JavaScript-кода, необходимого для работы wasm модуля в веб-среде.
* Просто компиляция в wasm и создание JavaScript-кода.

Мы рассмотрим оба способа ниже.

### Создание HTML и JavaScript

Это самый простой способ, который мы рассмотрим. С его помощью вы сможете использовать Emscripten для создания всего что нужно, чтобы ваш код работал в браузере как модуль WebAssembly.

1. Нам понадобится простой пример для компиляции. Скопируйте следующий код программы на Си и сохраните его в файле `hello.c` в новой папке на вашем локальном диске:

```cpp
#include <stdio.h>

int main(int argc, char \*\* argv) {
  printf("Hello World\n");
}
```

2. Теперь, используя терминал, перейдите в каталог, в котором находится ваш файл hello.c, и выполните следующую команду:

```bash
emcc hello.c -s WASM=1 -o hello.html
```

Рассмотрим параметры, которые мы передали компилятору:

* `-s WASM=1` — Указывает, что мы хотим получить wasm модуль. Если не использовать этот параметр, по умолчанию Emscripten просто создаёт asm.js;
* `-o hello.html` — Указывает, что мы хотим, чтобы Emscripten сгенерировал HTML-страницу `hello.html` запускающую наш код, а также сам модуль wasm и код JavaScript который позволит использовать модуль в веб-среде.

На этом этапе в вашем каталоге должны находится:

* Бинарный код модуля wasm (`hello.wasm`)
* Файл JavaScript, содержащий код связывающий нативные функции Си и JavaScript/wasm (`hello.js`)
* HTML-страница для загрузки, компиляции и инициализации wasm модуля, и отображающий его вывод в браузере (`hello.html`)
### Запуск вашего примера

Теперь, всё что нужно чтобы запустить полученный `hello.html` в браузере, это поддержка WebAssembly. Он включён по умолчанию в Firefox 52+, Chrome 57+ и последних версиях Opera. Также вы можете использовать модули WebAssembly в Firefox 47+, включив флаг `javascript.options.wasm` в *about:config*, или в Chrome 51+ и Opera 38+ перейдя в *chrome://flags* и включив флаг *Experimental WebAssembly.*

Если все работает как планировалось, вы должны увидеть надпись "Hello world" на открывшейся веб-странице и в JavaScript консоли вашего браузера. Поздравляем, вы только что скомпилировали программу на Си в WebAssembly и запустили её в своём браузере!

**Примечание:** На самом деле, если просто открыть полученный `hello.html`, то ничего работать не будет. Подразумевается что все файлы находятся на веб-сервере и вы запускаете страницу через `localhost/hello.html`. Для этих целей можно использовать отладочный веб-сервер Emscripten. Чтобы его запустить, откройте терминал, перейдите в каталог, в котором находятся ваши файлы и выполните команду `emrun hello.html`

### Использование собственного HTML шаблона

Вы можете использовать собственный шаблон HTML. Давайте посмотрим, как это сделать:

1. Прежде всего, сохраните следующий код в файле hello2.c в новом каталоге:

```cpp
#include <stdio.h>

int main(int argc, char \*\* argv) {
    printf("Hello World\n");

}
```

2. Найдите файл `shell_minimal.html` в вашем репозитории emsdk. Скопируйте его в подкаталог `html_template` внутри вашего нового каталога.
3. Теперь, используя терминал, перейдите в ваш новый каталог и выполните следующую команду:

```bash
emcc -o hello2.html hello2.c -O3 -s WASM=1 --shell-file html_template/shell_minimal.html
```

В этот раз мы использовали немного другие параметры компиляции:
    * Мы указали `-o hello2.html`, чтобы компилятор по прежнему генерировал необходимый JavaScript-код и `.html` файл.
    * Также, мы указали `--shell-file html_template/shell_minimal.html` чтобы компилятор использовал ваш шаблон для создания HTML страницы запускающей этот пример.
4. Теперь давайте запустим этот пример. Команда, указанная выше, сгенерирует файл `hello2.html`, который будет иметь тоже содержание что и шаблон, но с некоторым кодом, добавленным в процесс загрузки сгенерированного wasm, запускающим его и т.д. Откройте его в своём браузере, и вы увидите тот же результат, что и прошлом примере.

**Примечание:** вы можете указать компилятору создавать только JavaScript-кода, без HTML, используя внутри флага `-o`, `.js` вместо `.html` для формата выходного файла, например `emcc -o hello2.js hello2.c -O3 -s WASM=1`. После этого вы должны создать свой собственный HTML файл с нуля. Однако так делать не рекомендуется — Emscripten требуется большое количество связывающего кода для обработки операций выделения памяти, утечек памяти и других проблем, которые уже включены в предоставляемый шаблон. Намного легче использовать уже готовое решение, чем создавать свои собственные версии самому.

### Вызов пользовательской функции, определённой в Си

Если у вас есть функция определённая в коде на Си, которую вы хотите по необходимости вызывать из JavaScript, то вы можете использовать для этого функцию `ccall()` из Emscripten, и объявление `EMSCRIPTEN_KEEPALIVE` которое добавит вашу функцию в список экспортируемых функций (см. Почему функции в моем коде исчезают после компиляции и/или я получаю сообщение «Нет функций для обработки»). Давайте посмотрим, как это работает.

1. Для начала сохраните следующий код в файле `hello3.c` в новом каталоге:

```cpp
#include <stdio.h>
#include <emscripten/emscripten.h>

int main(int argc, char \*\* argv) {
    printf("Hello World\n");
}

#ifdef \_\_cplusplus
extern "C" {
#endif

void EMSCRIPTEN_KEEPALIVE myFunction(int argc, char \*\* argv) {
  printf("MyFunction Called\n");
}

#ifdef \_\_cplusplus
}
#endif
```

По умолчанию, код созданный Emscripten, всегда просто вызывает функцию `main()` , а остальные неиспользуемые функции удаляются. Добавьте определение `EMSCRIPTEN_KEEPALIVE` перед именем функции чтобы этого не происходило. Также вы должны подключить библиотеку `emscripten.h` для использования `EMSCRIPTEN_KEEPALIVE`.

**Примечание:** Мы используем блоки `#ifdef` чтобы, пример оставался рабочим если вы попытаетесь использовать C++ код. Из за различия в правилах преобразования имён между Си и Си++, этот код может сломаться, но мы написали его так, что функция будет рассматриваться как функция Си даже если вы будете использовать Си++.
2. Теперь добавьте `html_template/shell_minimal.html` в ваш новый каталог, просто для удобства. В настоящем проекте стоит размещать его в специально определённый каталог.
3. Теперь снова займёмся этапом компиляции. Внутри вашего последнего каталога, используя терминал, скомпилируйте ваш Си код следующей командой. (Обратите внимание что при компиляции обязательно нужно использовать опцию NO\_EXIT\_RUNTIME, иначе после выполнения функции `main()`, рабочий цикл будет завершён. Это приведёт, например, к вызову функции atexits и дальше будет невозможно использовать наш скомпилированный код. Другими словами это необходимо для правильной эмуляции Си.)

```bash
emcc -o hello3.html hello3.c -O3 -s WASM=1 --shell-file html_template/shell_minimal.html -s NO\_EXIT\_RUNTIME=1  -s EXTRA\_EXPORTED\_RUNTIME\_METHODS='["ccall"]'
```

4. Если вы снова запустите пример в своём браузере, вы увидите тоже самое что и до этого!
5. Теперь нам нужно вызвать нашу новую функцию `myFunction()` из JavaScript. Прежде всего, добавьте `<button>` как показано ниже, чуть выше первого открывающего тега `<script type='text/javascript'>`.

```html
<button class="mybutton">Run myFunction</button>
```

6. Теперь добавьте следующий код в конце первого элемента `<script>` (чуть выше закрывающего тега `</script>`):

```js
document.querySelector(".mybutton").addEventListener("click", function () {
  alert("check console");
  var result = Module.ccall(
    "myFunction", // name of C function
    null, // return type
    null, // argument types
    null,
  ); // arguments
});
```

Это показывает как использовать `ccall()` для вызова экспортируемой функции.

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

* emscripten.org — узнайте больше об Emscripten и разнообразии его настроек.
* Calling compiled C functions from JavaScript using ccall/cwrap
* Why do functions in my C/C++ source code vanish when I compile to JavaScript, and/or I get No functions to process?
* WebAssembly on Mozilla Research
* Compiling an Existing C Module to WebAssembly (en-US)


Использование WebAssembly JavaScript API - WebAssembly

Использование WebAssembly JavaScript API
========================================

Если вы уже компилировали модуль из другого языка, используя такие инструменты как Emscripten, или загружали и запускали код, то следующим шагом будет углублённое изучение возможностей WebAssembly JavaScript API. Эта статья даст необходимые знания по этому вопросу.

**Примечание:** Если вы незнакомы с фундаментальными понятиями, упомянутыми в этой статье, и вам нужны дополнительные объяснения, то вам нужно сначала прочитать про Основы WebAssembly.

Несколько простых примеров
--------------------------

Давайте запустим несколько примеров, которые объяснят как использовать WebAssembly JavaScript API, и как использовать его для загрузки wasm-модуля в web-странице.

**Примечание:** вы можете найти примеры кода в нашем репозитории webassembly-examples на GitHub.

### Подготовка примера

1. Для начала нам нужен wasm-модуль! Возьмите наш файл simple.wasm и сохраните копию в новой директории на своём локальном компьютере.
2. Далее, давайте создадим в той же директории что и wasm-модуль простой HTML-файл и назовём его `index.html` (можно использовать HTML шаблон если вы этого ещё не сделали).
3. Теперь, для того чтобы понять что происходит в коде модуля, давайте взглянем на его текстовое представление (которое мы также встречали в Перевод из текстового формата WebAssembly в wasm):
```

(module
  (func $i (import "imports" "imported_func") (param i32))
  (func (export "exported_func")
    i32.const 42
    call $i))
```

4. Во второй строчке вы видите что import имеет двухуровневое пространство имён - внутренняя функция `$i` импортирована из `imports.imported_func`. Нам нужно создать это двухуровневое пространство имён в JavaScript-объекте, который будет импортирован в wasm-модуль. Создайте `<script></script>` элемент в своём HTML-файле, и добавьте следующий код:

```js
var importObject = {
  imports: { imported\_func: (arg) => console.log(arg) },
};
```

### Загрузка wasm-модуля в потоке

Новшество в Firefox 58 - это возможность компилировать и создавать экземпляры (объекты) модулей WebAssembly непосредственно из исходников. Это достигается использованием методов `WebAssembly.compileStreaming()` и `WebAssembly.instantiateStreaming()` (en-US). Эти методы занимают меньше места чем их непотоковые аналоги, потому что они могут преобразовывать байт-код прямо в модуль или экземпляр модуля, исключая необходимость отдельного размещения ответа (`Response`) в объекте `ArrayBuffer` после загрузки файла.

Следующий пример (см. наш демонстрационный файл instantiate-streaming.html на GitHub и его работу вживую) показывает как использовать `instantiateStreaming()` чтобы загрузить wasm-модуль, импортировать JavaScript функцию в него, компилировать, создать его экземпляр и получить доступ к его экспортируемой функции. Все это в одном шаге.

Добавьте этот скрипт ниже первого блока кода:

```js
WebAssembly.instantiateStreaming(fetch("simple.wasm"), importObject).then(
  (obj) => obj.instance.exports.exported\_func(),
);
```

В конце этого действия мы вызываем нашу экспортированную из WebAssembly-функцию `exported_func`, которая в свою очередь вызывает нашу импортированную JavaScript-функцию `imported_func`, которая выводит в консоль значение (42), что хранится внутри экземпляра модуля WebAssembly. Если вы сейчас сохраните пример кода и загрузите его в браузер, который поддерживает WebAssembly, вы увидите это в действии!

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

### Загрузка wasm-модуля без потока

Если вы не можете или не хотите использовать методы описанные выше, то вы можете использовать вместо этого непотоковые методы `WebAssembly.compile` / `WebAssembly.instantiate` (en-US).

Эти методы не получают непосредственно доступ к байт-коду, так что требуется дополнительный шаг помещения ответа загрузки файла в объект `ArrayBuffer` перед компилированием и созданием экземпляра wasm-модуля.

Эквивалентный код будет выглядеть так:

```js
fetch("simple.wasm")
  .then((response) => response.arrayBuffer())
  .then((bytes) => WebAssembly.instantiate(bytes, importObject))
  .then((results) => {
    results.instance.exports.exported\_func();
  });
```

### Просмотр wasm в инструментах разработчика

В Firefox 54+, в отладочной панели инструментов разработчика имеется возможность отображения текстового представления любого wasm-кода, включённого в веб-страницу. Для того чтобы просмотреть его, вы можете перейти на отладочную панель и нажать на пункт "wasm://".

![](/ru/docs/WebAssembly/Using_the_JavaScript_API/wasm-debug.png)

В ближайших версиях в Firefox, в дополнении к просмотру wasm-кода как текста, разработчики будут иметь возможность отлаживать wasm используя текстовый формат (устанавливать точки останова, изучать стек вызовов, построчно переходить, и.т.д). См. WebAssembly debugging with Firefox DevTools в видео-анонсе.

Память
------

В низкоуровневой модели памяти WebAssembly, память представлена как диапазон смежных байт, называемых линейной памятью (Linear Memory), которая внутри модуля читается и записывается инструкциями загрузки и размещения значений. В этой модели памяти, любая инструкция загрузки или размещения может получить доступ к любому байту всей линейной памяти. Это необходимо для полноценного представления таких концепций языков C/C++ как указатели.

В отличии от C/C++ программы, где доступный диапазон памяти ограничен процессом, память доступная отдельному экземпляру WebAssembly ограничена до одного специфического (потенциально очень маленького) диапазона, который содержится в объекте памяти WebAssembly. Это позволяет единственному web-приложению использовать множество независимых библиотек (использующих WebAssembly) которые могут иметь отдельные и полностью изолированные друг от друга диапазоны памяти.

В JavaScript-коде, объект памяти WebAssembly можно считать объектом ArrayBuffer c изменяемыми размерами. Одно веб-приложение может создавать много таких независимых объектов памяти. Вы можете создать новый объект, используя конструктор WebAssembly.Memory(), который принимает аргументы начального и максимального размера буфера (опционально).

Давайте исследуем эту возможность рассмотрев небольшой пример.

Создайте ещё одну простую HTML страницу (скопируйте HTML шаблон) и назовите её `memory.html`. Добавьте `<script></script>` элемент на страницу.

1. Добавьте следующую строку в начало нашего скрипта, для создания экземпляра объекта памяти:

```js
var memory = new WebAssembly.Memory({ initial: 10, maximum: 100 });
```

Единицы измерения начальной (`initial`) и максимальной (`maximum`) памяти имеют фиксированный размер в 64KB. Это означает, что в нашем случае объект памяти при создании имеет 640KB, а его максимальный возможный размер будет 6.4MB.
 Объект памяти WebAssembly предоставляет свой хранимый диапазон байт через getter/setter свойства buffer, которое возвращает объект ArrayBuffer. Для примера, чтобы записать число 42 в первое слово линейной памяти, вы можете сделать это:

```js
new Uint32Array(memory.buffer)[0] = 42;
```

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

```js
new Uint32Array(memory.buffer)[0];
```

2. Попробуйте сделать это в вашем примере - сохраните то, что вы сделали, загрузите его в браузере, после чего попробуйте ввести вышеупомянутые строчки в JavaScript-консоль.
### Расширение памяти

Объект памяти может быть расширен с помощью вызова метода `Memory.prototype.grow()`, где аргументом будет количество единиц (размером в 64KB) памяти WebAssembly:

```js
memory.grow(1);
```

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

**Примечание:** Так как размер объекта `ArrayBuffer` неизменен, после успешного вызова метода `Memory.prototype.grow()` свойство buffer объекта памяти будет возвращать уже новый объект `ArrayBuffer` (с новым размером в свойстве byteLength) и любые предыдущие объекты ArrayBuffer станут в некотором роде "отсоединёнными", или отключёнными от низкоуровневой памяти, к которой они ранее относились.

Подобно функциям, диапазоны линейной памяти могут быть импортированы или определены внутри модуля. Также, модуль имеет возможность экспортировать свою память. Это означает, что JavaScript-код может получить доступ к объекту памяти WebAssembly либо c помощью создания нового объекта через конструктор `WebAssembly.Memory` и передачи его в импортируемый объект, либо с помощью получения объекта памяти через экспортируемый объект (через `Instance.prototype.exports` (en-US)).

### Более сложный пример

Давайте сделаем вышеупомянутые утверждения понятнее, рассмотрев более сложный пример работы с памятью, где WebAssembly-модуль импортирует объект памяти, который мы определили ранее, после чего JavaScript-код наполняет его с помощью массива целых чисел, а экспортируемая wasm-функция суммирует их.

1. Скопируйте файл memory.wasm в локальную директорию в которой вы работаете.

**Примечание:** вы можете увидеть текстовое представление модуля в файле memory.wat.
2. Откройте ваш файл `memory.html` и добавьте следующий код снизу вашего основного скрипта для загрузки, компилирования и создания экземпляра wasm-модуля:

```js
WebAssembly.instantiateStreaming(fetch("memory.wasm"), {
  js: { mem: memory },
}).then((results) => {
  // add code here
});
```

3. Так как модуль экспортирует свою память, которая была передана экземпляру этого модуля при его создании, мы можем наполнить ранее импортированный массив прямо в линейной памяти экземпляра модуля (`mem`), и вызвать экспортированную функцию `accumulate()` для расчёта суммы значений. Добавьте следующий код, в обозначенном месте:

```js
var i32 = new Uint32Array(memory.buffer);

for (var i = 0; i < 10; i++) {
  i32[i] = i;
}

var sum = results.instance.exports.accumulate(0, 10);
console.log(sum);
```

Обратите внимание на то, что мы создаём представление данных `Uint32Array` (en-US) с помощью свойства buffer объекта памяти (`Memory.prototype.buffer` (en-US)), а не самого объекта памяти.

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

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

**Примечание:** вы можете найти полную демонстрацию в файле memory.html (см. её также вживую) — эта версия использует функцию `fetchAndInstantiate()`.

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

Таблица WebAssembly - это расширяемый типизированный массив ссылок, доступ к которому может быть получен из JavaScript и WebAssembly кода. Так как линейная память предоставляет расширяемый массив незащищённых байт, слишком небезопасно размещать там ссылки, так как для движка ссылка является доверенным значением, чьи байты не должны быть прочитаны или записаны кодом напрямую по причинам безопасности, переносимости и стабильности.

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

Ссылки на функции необходимы для компиляции в таких языках как C/C++, которые имеют указатели на функции. В родной реализации C/C++, указатель на функцию представлен прямым адресом на код функции в виртуальном адресном пространстве процесса, и потому для ранее упомянутой безопасности, они не могут быть размещены прямо в линейной памяти. Вместо этого ссылки на функции размещаются в таблице, а её индексы, которые являются целыми числами могут быть размещены в линейной памяти и переданы куда угодно.

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

Таблицы могут изменятся с помощью метода `Table.prototype.set()` (en-US), который обновляет одно из значений в таблице, и метода `Table.prototype.grow()` (en-US), который увеличивает количество значений, которое может быть размещено в таблице. Это позволяет этому "непрямо-вызываемому набору функций" изменяться со временем, что необходимо для техник динамического связывания. Изменения немедленно становятся доступными с помощью метода `Table.prototype.get()` (en-US) в JavaScript-коде и wasm-модулях.

### Пример таблицы

Давайте взглянем на простой пример таблицы - модуль WebAssembly, который создаёт и экспортирует таблицу с двумя элементами: элемент под индексом 0 возвращает 13, а элемент под индексом 1 возвращает 42.

1. Сделайте локальную копию файла table.wasm в новой директории.

**Примечание:** вы можете посмотреть текстовое представление модуля в файле table.wat.
2. Создайте новую копию нашего HTML шаблона в той же директории и назовите его table.html.
3. Как и раньше загрузите, компилируйте, и создайте экземпляр вашего wasm-модуля, добавив следующий код в `<script>` элемент в тело документа:

```js
WebAssembly.instantiateStreaming(fetch("table.wasm")).then(
  function (results) {
    // add code here
  },
);
```

4. Теперь давайте получим доступ к данным в таблицах - добавим следующие строки в ваш код, в обозначенном месте:

```js
var tbl = results.instance.exports.tbl;
console.log(tbl.get(0)()); // 13
console.log(tbl.get(1)()); // 42
```

Этот код получает доступ к каждой ссылке на функцию, которая размещена в таблице, после чего вызывает её и выводит хранимое значение в консоль. Обратите внимание, что каждая ссылка на функцию получена с помощью вызова метода `Table.prototype.get()` (en-US), после чего мы добавили пару круглых скобок для вызова самой функции.

**Примечание:** вы можете найти нашу полную демонстрацию в файле table.html (см. её также вживую) — эта версия использует функцию `fetchAndInstantiate()`.

Глобальные переменные
---------------------

WebAssembly имеет возможность создавать экземпляры глобальных переменных, доступных как в JavaScript так и в экземплярах модулей WebAssembly (`WebAssembly.Module` (en-US)) посредством импорта или экспорта. Это очень полезная возможность, которая позволяет динамически связывать несколько модулей. Для создания глобальной переменной WebAssembly внутри вашего JavaScript-кода, используйте конструктор `WebAssembly.Global()` (en-US), который выглядит так:

```js
const global = new WebAssembly.Global({ value: "i32", mutable: true }, 0);
```

Вы можете видеть, что он принимает 2 параметра:

* Объект, который содержит 2 свойства, описывающих глобальную переменную:
    + `value`: это тип данных, который может быть одним из типов данных, позволенных внутри WebAssembly модуля — `i32`, `i64`, `f32`, или `f64`.
    + `mutable`: булево значение, определяющее что переменная может изменяться.
* Значение, которое содержит текущее значение переменной. Это может быть любое значение для типа к которому оно относится.

Что мы будем с этим делать? В следующем примере мы определим глобальную, изменяемую переменную с типом i32 и значением 0.

Значение глобальной переменной будет изменено на число `42` используя свойство `Global.value`, а после на `43` используя экспортированную функцию `incGlobal()` из модуля `global.wasm` (это добавит 1 к установленному значению и возвратит новое).

```js
const output = document.getElementById("output");

function assertEq(msg, got, expected) {
  output.innerHTML += `Testing ${msg}: `;
  if (got !== expected)
    output.innerHTML += `FAIL!<br>Got: ${got}<br>Expected: ${expected}<br>`;
  else output.innerHTML += `SUCCESS! Got: ${got}<br>`;
}

assertEq("WebAssembly.Global exists", typeof WebAssembly.Global, "function");

const global = new WebAssembly.Global({ value: "i32", mutable: true }, 0);

WebAssembly.instantiateStreaming(fetch("global.wasm"), { js: { global } }).then(
  ({ instance }) => {
    assertEq(
      "getting initial value from wasm",
      instance.exports.getGlobal(),
      0,
    );
    global.value = 42;
    assertEq(
      "getting JS-updated value from wasm",
      instance.exports.getGlobal(),
      42,
    );
    instance.exports.incGlobal();
    assertEq("getting wasm-updated value from JS", global.value, 43);
  },
);
```

**Примечание:** вы можете увидеть этот пример вживую на GitHub; смотрите также исходники.

Множественность
---------------

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

* Один модуль может иметь N экземпляров, точно так же как одно определение функции может произвести N замыканий.
* Один экземпляр модуля может использовать от 0 до 1 объекта памяти, который предоставляет "адресное пространство" экземпляра модуля. Будущие версии WebAssembly позволят иметь 0–N экземпляров объектов на один экземпляр модуля (см. Несколько таблиц и объектов памяти).
* Один экземпляр модуля может использовать от 0 до 1 объекта таблицы - это "адресное пространство для функций" экземпляра модуля используется для реализации С/С++ указателей на функции. Будущие версии WebAssembly позволят иметь 0–N экземпляров таблиц на один экземпляр модуля.
* Один объект памяти или объект таблицы может быть использован в 0-N экземплярах модулей - эти все экземпляры будут разделять одно и то же адресное пространство, позволяя выполнять динамическое связывание.

Чтобы ознакомится с множественностью в действии, смотрите нашу объясняющую статью Изменяющиеся таблицы и динамическое связывание.

Резюме
------

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

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

* webassembly.org
* Основы WebAssembly
* WebAssembly на Mozilla Research


Экспортируемые функции WebAssembly - WebAssembly

Экспортируемые функции WebAssembly
==================================

Экспортированные функции WebAssembly - это функции вашего модуля доступные в JavaScript. В этой статье более подробно описывается, что они из себя представляют.

Экспортированные… что?
----------------------

Экспортированные функции это просто JavaScript обёртки, которые вызывают функции модуля WebAssembly. При их использовании происходит неявное преобразование типов аргументов функции в типы, с которыми может работать WebAssembly (например, преобразование number в int32). Дальше эти аргументы передаются функции вашего модуля и она вызывается. Результат также преобразовывается и возвращается в JavaScript.

Вы можете получить список экспортированных функций двумя способами:

* Вызовите `Table.prototype.get()` (en-US) у существующей таблице;
* Через `Instance.exports` (en-US) существующего экземпляра модуля.

В любом случае вы получаете одну и туже обёртку функции вашего модуля. С точки зрения JavaScript, все экспортированные функции wasm являются функциями JavaScript, но они инкапсулированы экземпляром модуля wasm, и имеют только ограниченный способ доступа к ним.

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

Давайте посмотрим на пример, чтобы прояснить ситуацию (вы можете найти его на GitHub как table-set.html или запустить в своём браузере, и посмотреть текстовое представление модуля wasm):

```js
var otherTable = new WebAssembly.Table({ element: "anyfunc", initial: 2 });

WebAssembly.instantiateStreaming(fetch("table.wasm")).then((obj) => {
  var tbl = obj.instance.exports.tbl;
  console.log(tbl.get(0)()); // 13
  console.log(tbl.get(1)()); // 42
  otherTable.set(0, tbl.get(0));
  otherTable.set(1, tbl.get(1));
  console.log(otherTable.get(0)());
  console.log(otherTable.get(1)());
});
```

Здесь мы создаём таблицу (`otherTable`) из JavaScript используя конструктор `WebAssembly.Table`, после этого мы загружаем модуль `table.wasm` при помощи функции `WebAssembly.instantiateStreaming()` (en-US).

Затем мы получаем объект содержащий все функции, экспортированные из экземпляра модуля. Извлекаем ссылки на эти функции через `tbl.get(),` вызываем их и выводим результат работы в консоль. Затем мы используем `set()` чтобы таблица `otherTable` содержала ссылки на те же функции, что и таблица `tbl`.

Чтобы доказать это, мы получаем ссылки на функции из таблицы `otherTable` и вызываем их. При выводе в консоль они дают такие же результаты.

Они являются настоящими функциями
---------------------------------

В предыдущем примере возвращаемое значение каждого вызова `Table.prototype.get()` (en-US) является экспортированной функцией WebAssembly — это именно то, о чем мы говорили.

Стоит заметить что помимо того что они являются обёртками для функций WebAssembly, это обычные функции JavaScript. Если вы загрузите приведённый выше пример в браузере с поддержкой WebAssembly, и запустите следующие строки в консоли:

```js
var testFunc = otherTable.get(0);
typeof testFunc;
```

результатом выполнения будет `function`. Вы можете сделать с ней все тоже самое что и с другими функциями в JavaScript — `call()`, `bind()` и т.д. Вызов `testFunc.toString()` возвращает интересный результат:

```js
function 0() {
    [native code]
}
```

Это наводит на мысль о том что эта функция является обёрткой.

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

* Их свойство length это количество аргументов указанных в сигнатуре wasm функции.
* Их свойство name является результатом вызова `toString()` индекса функции в модуле wasm.
* Если вы попытаетесь вызвать экспортированную функцию wasm, которая принимает или возвращает значение типа i64, то это приведёт к ошибке, поскольку в настоящее время JavaScript не имеет точного способа представления i64. Однако в дальнейшем это может измениться - новый тип int64 рассматривается для будущих стандартов, который затем может использоваться wasm.


Загрузка и запуск кода WebAssembly - WebAssembly

Загрузка и запуск кода WebAssembly
==================================

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

Какие есть варианты?
--------------------

WebAssembly ещё не интегрирована с `<script type='module'>` или ES2015 оператором `import`, поэтому не существует пути, позволяющего использовать модули загрузки браузера для использования импорта.

Старые методы `WebAssembly.compile`/`WebAssembly.instantiate` (en-US) требуют создания `ArrayBuffer`, содержащего двоичный файл модуля WebAssembly после загрузки необработанных байтов, а затем скомпилировать/создать его экземпляр. Это аналог `new Function(string)`, за исключением того, что мы заменяем строку символов (исходный код JavaScript) буфером байтов массива (исходный код WebAssembly).

Более новые методы `WebAssembly.compileStreaming`/`WebAssembly.instantiateStreaming` (en-US) намного эффективнее - они выполняют свои действия непосредственно с необработанным потоком байтов, поступающих из сети, избавление от необходимости шага `ArrayBuffer`.

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

Используя Fetch
---------------

Fetch - это удобный современный API для извлечения сетевых ресурсов.

Самый быстрый и эффективный способ получить модуль wasm - использовать более новый метод `WebAssembly.instantiateStreaming()` (en-US), который может принять вызов `fetch()` в качестве первого аргумента и будет обрабатывать загрузку, компиляцию и создание экземпляра модуля за один шаг, получая доступ к необработанному байтовому коду при его потоковой передаче с сервера:

```js
WebAssembly.instantiateStreaming(fetch("simple.wasm"), importObject).then(
  (results) => {
    // Do something with the results!
  },
);
```

Если бы мы использовали более старый метод `WebAssembly.instantiate()` (en-US), который не работает в прямом потоке, нам потребовался бы дополнительный шаг преобразования преобразованного байт-кода в `ArrayBuffer`, вот так:

```js
fetch("module.wasm")
  .then((response) => response.arrayBuffer())
  .then((bytes) => WebAssembly.instantiate(bytes, importObject))
  .then((results) => {
    // Do something with the results!
  });
```

### Помимо перегрузок instantiate()

Функция `WebAssembly.instantiate()` (en-US) имеет две формы перегрузки - та, что показана выше, принимает байт-код для компиляции в качестве аргумента и возвращает `Promise`, которое разрешается для объекта, содержащего оба объекта скомпилированного модуля, и экземпляр этого. Объект выглядит так:

```js
{
  module: Module; // The newly compiled WebAssembly.Module object,
  instance: Instance; // A new WebAssembly.Instance of the module object
}
```

**Примечание:** Обычно мы заботимся только об экземпляре, но полезно иметь модуль на тот случай, если мы хотим его кешировать, поделиться им с другим работником или окном через `postMessage()` (en-US), или просто создать больше экземпляров.

**Примечание:** Вторая форма перегрузки принимает в качестве аргумента объект `WebAssembly.Module` (en-US) и возвращает `Promise`, непосредственно содержащее объект экземпляра, в качестве результата. См. Второй пример перегрузки (en-US).

### Выполнение вашего кода WebAssembly

Когда у вас есть экземпляр WebAssembly, доступный в вашем JavaScript, вы можете начать использовать его возможности, которые были экспортированы через свойство `WebAssembly.Instance.exports` (en-US). Ваш код может выглядеть примерно так:

```js
WebAssembly.instantiateStreaming(fetch("myModule.wasm"), importObject).then(
  (obj) => {
    // Call an exported function:
    obj.instance.exports.exported\_func();

    // or access the buffer contents of an exported memory:
    var i32 = new Uint32Array(obj.instance.exports.memory.buffer);

    // or access the elements of an exported table:
    var table = obj.instance.exports.table;
    console.log(table.get(0)());
  },
);
```

**Примечание:** Для получения дополнительной информации о том, как работает экспорт из модуля WebAssembly, ознакомьтесь с разделами Использование JavaScript API WebAssembly, и Понимание текстового формата WebAssembly.

Используя XMLHttpRequest
------------------------

`XMLHttpRequest` несколько старше, чем Fetch, но всё же может успешно использоваться для получения типизированного массива. Опять же, если предположить, что наш модуль называется `simple.wasm`:

1. Создайте новый экземпляр `XMLHttpRequest()` и используйте его метод `open()` для открытия запроса, задав для метода запроса значение `GET` и указав путь к файлу, который мы хотим получить.
2. Ключевой частью этого является установка типа ответа `'arraybuffer'` с помощью свойства `responseType`.
3. Затем отправьте запрос с помощью `XMLHttpRequest.send()`.
4. Затем мы используем обработчик событий `onload` для вызова функции после завершения загрузки ответа - в этой функции мы получаем буфер массива из `response` и затем передайте это в наш метод `WebAssembly.instantiate()` (en-US), как мы это делали с Fetch.

Финальный код выглядит так:

```js
request = new XMLHttpRequest();
request.open("GET", "simple.wasm");
request.responseType = "arraybuffer";
request.send();

request.onload = function () {
  var bytes = request.response;
  WebAssembly.instantiate(bytes, importObject).then((results) => {
    results.instance.exports.exported\_func();
  });
};
```

**Примечание:** вы можете увидеть пример этого в действии в xhr-wasm.html.