Индексированные коллекции

Индексированная коллекция — это структура данных, в которой элементы хранятся и доступны с помощью нумерованных индексов. Значениям, хранящимся в индексированной коллекции, присваиваются нумерованные индексы, начиная с 0 Этот шаблон называется «нулевой индексацией». Затем вы можете получить доступ к значениям, хранящимся в индексированной коллекции, ссылаясь на их индексы.

Множество

Массив — это контейнер, который может содержать ноль или более значений любого типа данных, включая сложные объекты или другие массивы. Значения, хранящиеся в массиве, иногда называют «элементами» массива.

Создать массив

Как и в случае с примитивными типами данных, существует два подхода к созданию массива: в виде литерала массива или путем вызова встроенного в JavaScript конструктора Array() с помощью new Array() . Присвоение массива переменной обеспечивает высокую переносимость и повторяемость способа присвоения нескольких значений одному идентификатору.

В синтаксисе литералов массива используется набор скобок ( [] ), окружающих ноль или более значений данных, разделенных запятыми:

const myArray = [];

Синтаксис конструктора массива использует встроенный в JavaScript объект Array в качестве конструктора с ключевым словом new :

const myArray = new Array();

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

const myArray = [ true, null, "String", false ];

myArray;
> [ true, null, "String", false ]

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

const myArray = new Array( true, null, "String", false );

myArray;
> Array(4) [ true, null, "String", false ]

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

// Firefox:\
const myArray = new Array( 10 );

myArray;
> Array(10) [ <10 empty slots> ]
// Chrome:
const myArray = new Array( 10 );

myArray;
> (10) [empty × 10]

Массивы, содержащие пустые слоты (иногда называемые «разреженными массивами»), представляют собой особый случай. Вместо того, чтобы содержать undefined или явно null значение, пустые слоты часто, но не всегда, рассматриваются как undefined значения в других частях языка.

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

const myArray = [ true,, true, false ];

myArray;
> Array(4) [ true, <1 empty slot>, true, false ]

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

const myArray = [ 1,, 3, 4 ];

myArray.length;
> 4

for( const myValue of myArray ) {
  console.log( myValue + 10 );
}
> 11
> NaN
> 13
> 14

Такое поведение является пережитком некоторых ранних дизайнерских решений JavaScript. Избегайте использования разреженных массивов в современной разработке.

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

const arrayLiteral = [];
const arrayConstructor = new Array();

typeof arrayLiteral;
> "object"

arrayLiteral;
> Array []
    length: 0
    <prototype>: Array []

typeof arrayConstructor;
> "object"

arrayConstructor;
> Array []
    length: 0
    <prototype>: Array []

Поскольку эти два результата идентичны, а синтаксис литерала массива является более кратким и буквальным, мы настоятельно рекомендуем всегда использовать синтаксис литерала массива вместо new Array() .

Доступ к значениям массива

Вы можете получить доступ к отдельным элементам внутри массива, используя скобочную запись, набор скобок ( [] ), следующий за массивом или его идентификатором, который содержит число, относящееся к индексу этого элемента:


[ "My string", "My other string" ][ 1 ];
> "My other string"

const myArray = [ "My string", 50, true ];

myArray[ 0 ];
> "My string"

myArray[ 1 ];
> 50

myArray[ 2 ];
> true

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

const myArray = [ "My string", 50, true ];

myArray[ 2 ];
> true

myArray[ "2" ];
> true

Попытка получить доступ к элементу, находящемуся за пределами определенных в массиве, приводит к undefined результату, а не к ошибке:

const myArray = [ "My string", 50, true ];

myArray[ 9 ];
> undefined

Деструктуризация задания

Деструктуризация присваивания — это краткий способ извлечения диапазона значений из массивов или объектов и присвоения их набору идентификаторов. Этот процесс иногда называют «распаковкой» исходной структуры данных, хотя он не изменяет исходный массив или объект.

Присвоение деструктуризации использует список идентификаторов в виде массива или объекта для отслеживания значений. В своей простейшей форме, называемой деструктуризацией шаблона привязки , каждое значение распаковывается из массива или объекта и присваивается соответствующей переменной, инициализируемой с помощью let или const (или var ):

const myArray = [ "A string", "A second string" ];
const [ myFirstElement, mySecondElement ] = myArray;

const myObject = { firstValue: false, secondValue: true };
const { myProp, mySecondProp } = myObject;

myFirstElement;
> "My string"

mySecondElement;
> "Second string"

myProp;
> false

mySecondProp;
> true

Используйте фигурные скобки ( {} ), чтобы деструктурировать объект, и квадратные скобки ( [] ), чтобы деструктурировать массив.

const myArray = [ false, true ];
const myObject = { firstValue: false, secondValue: true };

const [ myProp, mySecondProp ] = myObject;
> Uncaught TypeError: myObject is not iterable

const { myElement, mySecondElement } = myArray;

myElement
> undefined

mySecondElement;
> undefined

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

const myArray = [ 1, 2, 3 ];
const [ myElement, mySecondElement, myThirdElement ] = myArray;

myElement;
> 1

mySecondElement;
> 2

myThirdElement;
> 3

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

const myObject = { firstValue: 1, secondValue: 2, thirdValue 3 };
const { secondValue, thirdValue, firstValue } = myObject;

firstValue;
> 1

secondValue;
> 2

thirdValue;
> 3

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

const myArray = [ 1, 2, 3 ];
const [ firstValue,, secondValue ] = myArray;

firstValue;
> 1

secondValue;
> 3

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

const myArray = [ true, ];
const [ firstValue = "Default string.", secondValue = "Default string." ] = myArray;

firstValue;
> true

secondValue;
> "Default string."

Деконструкция не приводит значения к определенным типам. Это означает, что «ложные» значения, такие как пустые строки ( "" ) или null , по-прежнему считаются значимыми деконструированными значениями:

const myArray = [ false, null, 0, "",, undefined ];
const [ falseValue = true, nullValue = true, zeroValue = true, emptyStringValue = true, emptySlot = true, undefinedValue = true ] = myArray;

falseValue;
> false;

nullValue;
> null

zeroValue;
> 0

emptyStringValue;
> ""

emptySlot;
> true

undefinedValue;
> true

Оператор распространения

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

const myArray = [ 1, 2, 3 ];

console.log( ...myArray );
> 1 2 3

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

const myArray = [ 4, 5, 6 ];
const mySecondArray = [1, 2, 3, ...myArray ];

mySecondArray;
> Array(6) [ 1, 2, 3, 4, 5, 6 ]

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

Для массивов и строк синтаксис расширения применяется только в том случае, если ожидается ноль или более аргументов в вызове функции или элементов в массиве. Первый пример синтаксиса оператора расширения в этом разделе работает, поскольку он передает ...myArray в качестве аргумента встроенному методу console.log .

Например, вы не можете присвоить распространяемые данные переменной вне другого массива:

const myArray = [ 1, 2, 3 ];
const spreadVariable = ...myArray;
> Uncaught SyntaxError: Unexpected token '...'

Но вы копируете массив, помещая исходный массив в литерал массива:

const myArray = [ 1, 2, 3 ];
const spreadArray = [ ...myArray ];

spreadArray;
> Array(3) [ 1, 2, 3 ]

Чтобы объединить элементы, составляющие два или более массива, в один массив:

const myArray = [ 1, 2, 3 ];
const mySecondArray = [ 4, 5, 6 ];
const myNewArray = [ ...myArray, ...mySecondArray ];

myNewArray;
> Array(6) [ 1, 2, 3, 4, 5, 6 ]

Или передать элементы массива в качестве отдельных аргументов при вызове функции:

const myArray = [ true, false ];
const myFunction = ( myArgument, mySecondArgument ) => {
    console.log( myArgument, mySecondArgument );
};

myFunction( ...myArray );
> true false

Оператор распространения был расширен для работы с объектными литералами в ES2018 . Как и в случае с массивами, вы можете использовать оператор распространения для дублирования или объединения объектов:

const myObj = { myProperty : true };
const mySecondObj = { ...myObj };

mySecondObj;
> Object { myProperty: true }
const myFirstObj = { myProperty : true };
const mySecondObj = { additionalProperty : true };
const myMergedObj = { ...myFirstObj, ...mySecondObj };

myMergedObj;
> Object { myProperty: true, additionalProperty: true }

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

const myCustomPrototype = { protoProp: "My prototype." };
const myObj = Object.create( myCustomPrototype, {
    myEnumerableProp: {
        value: true,
        enumerable: true
    },
    myNonEnumerableProp: {
        value: false,
        enumerable: false
    }
});
const myNewObj = { ...myObj };

myObj;
> Object { myEnumerableProp: true,  }
    myEnumerableProp: true
    myNonEnumerableProp: false
    <prototype>: Object { protoProp: "My prototype." }

myNewObj;
> Object { myEnumerableProp: true }
    myEnumerableProp: true
    <prototype>: Object {  }

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

Оператор отдыха

Хотя синтаксис самого оператора тот же, оператор rest ( ... ) выполняет противоположную функцию в зависимости от контекста, в котором он используется. Вместо расширения итерируемой структуры данных на отдельные элементы, как это происходит при деструктурировании присваивания или как параметр функции , оператор rest объединяет элементы в повторяемую структуру данных. Название происходит от того факта, что оно используется для сбора «оставшейся части» набора значений данных.

При использовании с назначением деструктуризации этот синтаксис называется синтаксисом «остаточного свойства».

const myArray = [ "First", "Second", "Third", "Fourth", "Fifth" ];

[ myFirstElement, mySecondElement, ...remainingElements ] = myArray;

myFirstElement;
> "First"

mySecondElement;
> "Second"

remainingElements;
> Array(3) [ "Third", "Fourth", "Fifth"]

Когда этот синтаксис используется для предоставления неопределенного числа аргументов функции , он называется синтаксисом «остального параметра»:

function myFunction( ...myParameters ) {
    let result = 0;
    myParameters.forEach( ( myParam ) => {
        result += myParam;
    });
    return result;
};

myFunction( 2, 2 );
> 4

myFunction( 1, 1, 1, 10, 5 );
> 18

myFunction( 10, 11, 25 );
> 46

%TypedArray%

Типизированные массивы — это функция ES6, предназначенная для хранения структурированных двоичных данных, например, при работе с загруженными файлами или WebGL .

Как и в случае с символами , встроенная функция %TypedArray% (обычно документируемая как %TypedArray% или @@TypedArray , чтобы ее нельзя было спутать с глобальным свойством) не является функцией-конструктором в обычном смысле, и вы не можете вызовите его с помощью new или вызовите напрямую. Вместо этого %TypedArray% относится к родительскому суперклассу отдельных конструкторов, каждый из которых работает с определенным форматом двоичных данных. Внутренний суперкласс %TypedArray% предоставляет свойства и служебные методы, которые наследуют все подклассы конструктора %TypedArray% и их экземпляры.

Проверьте свое понимание

Учитывая `const myArray = [ 30, 50, 70 ];`, что возвращает `myArray[1]`?

50
70
30

Если myArray имеет три значения, что возвращает myArray[9]?

Undefined
9
Сообщение об ошибке
Null