-
Notifications
You must be signed in to change notification settings - Fork 686
Добавляет информацию в статью о DataView #5888
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
marss-hub
wants to merge
5
commits into
doka-guide:main
Choose a base branch
from
marss-hub:add-info-about-dataview
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
0dd54c7
Добавляет информацию в статью о DataView
marss-hub 0c8563a
Исправлена опечатка в теге
marss-hub ce52374
Убирает из доки placeholder
vitya-ne c58938f
Исправляет опечатку
vitya-ne 660fcb4
Merge branch 'main' into add-info-about-dataview
ra1nbow1 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
--- | ||
title: "`DataView`" | ||
description: "Объект для представления бинарных данных из буфера в нужном порядке байтов." | ||
description: "Объект для нетипизированного представления бинарных данных из буфера в нужном формате и порядке байтов" | ||
authors: | ||
- doka-dog | ||
- marss-hub | ||
keywords: | ||
- typed array | ||
- indexed collection | ||
|
@@ -14,49 +14,163 @@ related: | |
- js/array-buffer | ||
tags: | ||
- doka | ||
- placeholder | ||
--- | ||
|
||
## Кратко | ||
|
||
Объект, который предоставляет низкоуровневое API (Application Programming Interface, интерфейс программирования приложения) для записи и чтения данных из [`ArrayBuffer`](/js/array-buffer/) или [`SharedArrayBuffer`](/js/shared-array-buffer/). Является частью типизированного массива. | ||
`DataView` — это специальный объект для обращения к _нетипизированному_ представлению данных из [`ArrayBuffer`](/js/array-buffer/). Он содержит уникальные методы, позволяющие обратиться к данным, задавая их тип в момент обращения с возможностью явно указать порядок байтов. | ||
|
||
Типизированные массивы упрощают работу с тяжёлыми данными, например, видео, аудио и анимациями. Их часто используют с различными API — WebGL, Canvas 2D, XMLHttpRequest2 и так далее. | ||
Поскольку `DataView` предоставляет низкоуровневое API для записи и чтения данных из `ArrayBuffer`, это делает его очень гибким инструментом для работы с бинарными форматами данных — изображениями, аудио и видеофайлами, сетевыми запросами. Если требуется взаимодействовать с буфером, где хранятся данные разного типа, то `DataView` просто необходим. | ||
|
||
## Пример | ||
|
||
```js | ||
const littleEndian = (() => { | ||
const buffer = new ArrayBuffer(2) | ||
new DataView(buffer).setInt16(0, 256, true) | ||
const buffer = new ArrayBuffer(4); | ||
const dataView = new DataView(buffer); | ||
|
||
return new Int16Array(buffer)[0] === 256 | ||
})() | ||
dataView.setUint8(0, 255); | ||
dataView.setUint8(1, 255); | ||
|
||
console.log(littleEndian) | ||
// true или false | ||
console.log(dataView.getUint8(0)); | ||
// 255 | ||
|
||
console.log(dataView.getUint16(0)); | ||
// 65535 | ||
``` | ||
|
||
## Как пишется | ||
### Создание представления | ||
|
||
`DataView`, как и `TypedArray`, используют для представления данных из `ArrayBuffer`. Этот объект позволяет контролировать порядок байтов, который может не совпадать с их порядком в операционной системе пользователя. К примеру, через `DataView` можно установить порядок от младшего к старшему (little-endian) или смешанный (middle-endian). | ||
Чтобы создать `DataView` используйте оператор `new`: | ||
|
||
Чтобы создать `DataView`, обязательно используйте оператор `new`. Обратите внимание, что значение `DataView` нельзя изменять. Оно устанавливается один раз при создании объекта. | ||
```js | ||
new DataView(buffer, [byteOffset], [byteLength]); | ||
``` | ||
|
||
### Свойства | ||
- `buffer` — ссылка на бинарные данные `ArrayBuffer`; | ||
- `byteOffset` — стартовая позиция данных для представления в байтах (смещение), по умолчанию - 0; | ||
- `byteLength` — количество читаемых данных (в байтах) из `buffer`, по умолчанию - до конца буфера. | ||
|
||
<aside> | ||
|
||
Обратите внимание: | ||
⚠️ В отличие от типизированных массивов `DataView` никогда не создает буфер автоматически. | ||
⚠️ Значение `DataView` задается один раз при создании объекта и не изменяемо в дальнейшем. | ||
|
||
</aside> | ||
|
||
Мы можем просто создать представление `DataView` для всего буфера: | ||
|
||
```js | ||
// Создание буфера указанного размера | ||
const buffer = new ArrayBuffer(16); | ||
// Создание представления DataView | ||
const dataView = new DataView(buffer); | ||
``` | ||
|
||
- `buffer` — на какой `ArrayBuffer` ссылается представление. Только для чтения. | ||
- `byteLength` — размер представления в байтах. Только для чтения. | ||
- `byteOffset` — смещение представления в байтах от начального значения в `ArrayBuffer`. Только для чтения. | ||
Или создать представление для его части, указав в аргументах `byteOffset` и `byteLength`: | ||
|
||
```js | ||
const buffer = new ArrayBuffer(16); | ||
// Создание представления, в котором со смещением на 2 считываем 4 байта | ||
const dataView = new DataView(buffer, 2, 4); | ||
``` | ||
|
||
### Свойства | ||
Свойства `DataView` аналогичны аргументам его конструктора: | ||
- `buffer` — ссылка на `ArrayBuffer` на который ссылается представление. Только для чтения; | ||
- `byteLength` — размер представления в байтах. Только для чтения; | ||
- `byteOffset` — смещение представления `DataView` в байтах от начального значения в `ArrayBuffer`. Только для чтения. | ||
|
||
### Методы | ||
|
||
В качестве методов используют разные числовые форматы. Методы `get()` читают данные из нужного буфера, а `set()` их записывают. Например, `.getInt8()`, `.getUnit8()`, `.setFloat64()`, `.setBigInt64()`. | ||
Имена методов `DataView` удобно связаны с числовыми типами (`uint8`, `float64`, ...), при этом методы начинающиеся с `get` читают данные из буфера, а начинающиеся с `set` их записывают. Например: `.getInt8()`, `.getUint8()`, `.setFloat64()`, `.setBigInt64()` и т. д. | ||
|
||
```js | ||
// Создаем бинарный массив размером 4 байта | ||
const buffer = new Uint8Array([0, 42, 0, 42]).buffer; | ||
const dataView = new DataView(buffer); | ||
|
||
// Получим 8-битное число на позиции 0 | ||
console.log(dataView.getUint8(0)); | ||
// 0 | ||
|
||
// Теперь на той же позиции 0, получим 16-битное число, но оно уже состоит из двух байт | ||
console.log(dataView.getUint16(0)); | ||
// 42 | ||
|
||
// Теперь на той же позиции 0, получим 32-битное число, но оно уже состоит из четырех байт | ||
console.log(dataView.getUint32(0)); | ||
// 2752554 | ||
|
||
// Запишем нули на позицию 0 для 16-битного числа | ||
dataView.setUint16(0, 0); | ||
|
||
// Теперь 32-битное число изменилось | ||
console.log(dataView.getUint32(0)); | ||
// 42 | ||
``` | ||
|
||
[Список всех методов `DataView`](https://tc39.es/ecma262/multipage/structured-data.html#sec-dataview.prototype.constructor). | ||
|
||
## Как понять | ||
|
||
_Порядок байтов (endianness)_ — последовательность байтов, в которой информация хранится в памяти компьютера. По умолчанию используется порядок от старшего к младшему (big-endian). | ||
### Указание порядка байтов | ||
|
||
_Порядок байтов (endianness)_ — последовательность байтов, в которой информация хранится в памяти компьютера. По умолчанию в `DataView` используется порядок от старшего к младшему (big-endian). Про память подробнее вы можете узнать из статьи «[Как устроена память](/tools/trivial-memory-model/)». | ||
|
||
`DataView` дает возможность явно указывать порядок байтов в момент чтения или записи данных. В обычных `TypedArray` такой возможности нет. Возможность указания порядка байтов особенна важна когда порядок байтов в данных отличается от используемого в операционной системе. [Подробнее о порядке байтов](https://developer.mozilla.org/en-US/docs/Glossary/Endianness). | ||
|
||
```js | ||
const buffer = new ArrayBuffer(4); | ||
const dataView = new DataView(buffer); | ||
|
||
// Запишем число 123 с явным указанием big-endian порядка байтов, для этого укажем false | ||
dataView.setUint16(0, 123, false); | ||
|
||
// Читаем число из буфера с указанием порядка big-endian | ||
console.log(dataView.getUint16(0, false)); | ||
// 123 - все верно | ||
|
||
// Прочитаем число из буфера КАКИМ БЫ ОНО БЫЛО с указанием порядка little-endian | ||
console.log(dataView.getUint16(0, true)); | ||
// 31488 - совсем другое число! | ||
``` | ||
|
||
<details> | ||
<summary>Порядок байтов в операционной системе</summary> | ||
|
||
Пример того, как `DataView` позволяет контролировать порядок байтов, который (как уже упоминалось выше) может не совпадать с их порядком в системе пользователя: | ||
|
||
```js | ||
const littleEndian = (() => { | ||
const buffer = new ArrayBuffer(2); | ||
new DataView(buffer).setInt16(0, 256, true); | ||
|
||
return new Int16Array(buffer)[0] === 256; | ||
})(); | ||
|
||
console.log(littleEndian); | ||
// true или false | ||
``` | ||
|
||
Обратите внимание, по умолчанию `DataView` использует именно big-endian, однако многие платформы используют little-endian. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Давай перечислим тут в скобочках несколько этих платформ. Если не ошибаюсь, то они и есть самые часто используемые: Windows, Linux, macOs. |
||
|
||
</details> | ||
|
||
### Выход за границы буфера | ||
`DataView` сам контролирует соблюдение границ буфера. Попытка прочитать данные за пределами переданного `ArrayBuffer` выбросит ошибку `RangeError`. Это удобно и позволяет избежать трудноуловимых багов. | ||
|
||
```js | ||
const buffer = new ArrayBuffer(2); | ||
const dataView = new DataView(buffer); | ||
|
||
console.log(dataView.getUint32(0)); | ||
// Выдаст ошибку: Uncaught RangeError: Offset is outside the bounds of the DataView | ||
console.log(dataView.getUint16(1)); | ||
// Выдаст ошибку: Uncaught RangeError: Offset is outside the bounds of the DataView | ||
``` | ||
|
||
### Производительность | ||
Использование `DataView` дает большую гибкость и контроль, но ради этого приходится жертвовать скоростью. При каждом вызове метода чтения или записи, `DataView` выполняет несколько дополнительных проверок ([Согласно описанию в спецификации ECMAScript см. секции GetViewValue и SetViewValue](https://tc39.es/ecma262/#sec-getviewvalue)) — например, проверки выхода за границы буфера, проверка значения endianness и т. п. | ||
|
||
Про память подробнее узнаете из статьи «[Как устроена память](/tools/trivial-memory-model/)». | ||
Разница в скорости не будет заметна для большинства единичных задач. Однако в высокопроизводительных сценариях, например, при обработке каждого пикселя в изображении использование `TypedArray` с помощью `uint8array[i]` или `uint8array.map()` будет ощутимо быстрее, чем с обработка с применением методов `DataView`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
name: 'Светлана Маркова' | ||
url: https://github.com/marss-hub | ||
photo: svetlana.jpeg | ||
--- |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
А в каком случае тут будет
false
? Было бы здорово чуть подробнее это описать.