Хаки для создания массивов JavaScript

1656577586 haki dlya sozdaniya massivov javascript

автор Глад Чинда

Полезные советы по созданию и клонированию массивов в JavaScript.

IH842JnVoctZM6QoKOfXQe8luuYHXHjMuNxf
Оригинальное фото Маркуса Список на Unsplash

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

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

Массивы в JavaScript являются высокоуровневыми объектами, похожими на список свойство длины и целые свойства как индексы

В этой статье я делюсь парой лайфхаков для создания новых массивов JavaScript или клонирования существующих.

Создание массивов: конструктор массива

Самым популярным методом создания массивов является использование литерал массива синтаксис, который очень прост. Однако если вы хотите динамически создавать массивы, синтаксис литерала массива не всегда может быть лучшим методом. Альтернативным методом является использование Array конструктор.

Вот простой фрагмент кода, показывающий использование Array конструктор.

Из предыдущего фрагмента мы видим, что Array Конструктор создает массивы по-разному в зависимости от получаемых им аргументов.

Новые массивы: с определенной длиной

Давайте подробнее рассмотрим, что происходит при создании нового Array заданной длины Конструктор просто устанавливает length свойство массива заданной длины, без установки ключей.

HuAR3m0WmxP390Ezk4Ufyam-9vlyDzwNvEzi

Из приведенного выше фрагмента, у вас может возникнуть соблазн подумать, что для каждого ключа в массиве установлено значение undefined. Но реальность такова, что эти ключи никогда не были установлены (они не существуют).

Следующая иллюстрация объясняет:

wtfHBQo1MBofKp-EVs-IB6qqq07cfM18rK8I

Это делает бесполезными попытки использовать любой из методов итерации массива, например map(), filter() или reduce() манипулировать массивом. Скажем, мы хотим заполнить каждый индекс в массиве числом 5 как ценность. Мы попробуем следующее:

1OHTGXHuG93TuWcOpzRVtUNjoB-BFP3Pykq5

Мы видим это map() здесь не сработало, потому что свойства индекса не существуют в массиве – только length имущество существует.

Давайте рассмотрим разные способы решения этой проблемы.

1. Использование Array.prototype.fill()

The fill() способ заполняет все элементы массива от исходного индекса до конечного индекса статическим значением. Конечный индекс не входит. Вы можете узнать больше о fill() здесь.

Заметьте, что fill() работать только в браузерах с поддержкой ES6.

Вот простая иллюстрация:

w3CWlvnWqG5VEy6qupnAYvTqECGhPdj3P9Wu

Здесь мы смогли заполнить все элементы нашего созданного массива. 5. Вы можете установить любое статическое значение для различных индексов массива с помощью fill() метод.

2. Использование Array.from()

The Array.from() метод создает новый, мелко скопированный Array экземпляр из массива или итерационного объекта. Вы можете узнать больше о Array.from() здесь.

Заметьте, что Array.from() работать только в браузерах с поддержкой ES6.

Вот простая иллюстрация:

XfZGhDWQWU1VwxliMKIjYgHuwYvkfvPSBkVT

Вот теперь мы имеем правду undefined значения, установленные для каждого элемента массива с помощью Array.from(). Это означает, что теперь мы можем использовать такие методы, как .map() и .filter() на массив, поскольку свойства индекса теперь существуют.

Еще одна вещь, о которой следует обратить внимание Array.from() заключается в том, что он может принимать второй аргумент, являющийся a функция карты. Он будет вызван для каждого элемента массива. Это делает звонки лишними .map() после Array.from().

Вот простой пример:

UgaAHFIo4xzuw4cc4bI1iaxaPzGHKkTCbjYK

3. Использование оператора распространения

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

Вот простая иллюстрация использования оператора распространения:

gZrwaPsFq15WkPf2BnuAb2wA54JdIEXx7VNv

Вы можете пойти вперед и использовать такие методы, как .map() и .filter() на массив, поскольку свойства индекса теперь существуют.

Использование Array.of()

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

Хотя Array.of(5) создает новый массив с одним элементом, 5и свойство длины 1, Array(5) создает новый пустой массив с 5 пустыми слотами и свойством длины 5.

var array1 = Array.of(5); // [5]
var array2 = Array(5); // Array(5) {length: 5}

Кроме этой большой разницы, Array.of() ведет себя так же, как Array конструктор. Вы можете узнать больше о Array.of() здесь.

Заметьте, что Array.of() работать только в браузерах с поддержкой ES6.

Превращения в массивы: подобные массивам и итерации

Если вы достаточно долго писали функции JavaScript, вы уже должны знать о arguments объект — какой есть подобные массиву объект, доступный в каждой функции для хранения списка аргументов, полученных функцией. Хотя arguments Объект похож на массив, он не имеет доступа к Array.prototype методы

До ES6 вы обычно видели фрагмент кода, подобный приведенному ниже, когда пытались преобразовать файл arguments объект к массиву:

NaMaYAla-PzcPacVZGr3E03twovKgKTuRVwm

С Array.from() или оператор распространения, вы можете удобно превратить любой объект, подобный массиву, в массив. Итак, вместо этого:

var args = Array.prototype.slice.call(arguments);

вы можете сделать любое из этих:

// Using Array.from()
var args = Array.from(arguments);

// Using the Spread operator
var args = [...arguments];

Это также касается iterables как показано на следующей иллюстрации:

87TEnXS9-qV7Lak1XBBcEYiQVvh96FqXDJXc

Пример: Функция диапазона

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

range(start: number, end: number, step: number) => Array<number>

Вот фрагмент кода:

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

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

Вот некоторые результаты вызова range() функция, определенная в приведенном выше фрагменте кода:

zFBQwh8KfkoDDWXcZDl8YnDe7e9jBEsocdCa

Вы можете получить демо-версию кода в реальном времени, запустив следующую ручку Codepen:

Просмотрите Pen QxeXzm от Glad Chinda (@gladchinda) на CodePen.

Клонирование массивов: вызов

В JavaScript массивы и объекты являются типами ссылок. Это означает, что, когда переменной назначается массив или объект, переменной назначается ссылка на место в памяти, где хранился массив или объект.

Массивы, как и все другие объекты в JavaScript, являются типами ссылок. Это означает, что массивы копируются по ссылке, а не по значению.

Хранение справочных типов имеет следующее:

1. Подобные массивы не равны.

brYlg3Dp3gVRqGqHGkMBR2XR7eLvWQK8xymc

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

2. Массивы копируются по ссылке, а не по значению.

PZF-lU5f4C-OWkNLeF-q4g9T2anP6k88PPr1

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

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

Клонирование массивов: хаки

1. Использование Array.prototype.slice()

The slice() способ создает неглубокую копию части массива, не изменяя массив. Вы можете узнать больше о slice() здесь.

Хитрость состоит в том, чтобы позвонить slice() или с0 как единый аргумент или вообще без аргументов:

// with O as only argument
array.slice(0);

// without argument
array.slice();

Вот простая иллюстрация клонирования массива с помощью slice():

-XUoysUS92IrVW9lYY6EkJHXv8vKw0yahdaW

Вот это можно увидеть array2 является клоном array1 с такими же элементами и длиной. Однако они указывают на разные места в памяти и в результате не равны. Вы также заметите это, когда мы вносим изменения в array2 удалив последний элемент, array1 остается неизменным.

2. Использование Array.prototype.concat()

The concat() Метод используется для объединения двух или более массивов, что приводит к созданию нового массива, в то время как исходные массивы остаются неизменными. Вы можете узнать больше о concat() здесь.

Хитрость состоит в том, чтобы позвонить concat() или с пустым массивом ([]) как аргумент или вообще без каких-либо аргументов:

// with an empty array
array.concat([]);

// without argument
array.concat();

Клонирование массива с помощью concat() очень похож на использование slice(). Вот простая иллюстрация клонирования массива с помощью concat():

OXjY30kwODk5622BQraHtZfHxN5d5gewTeZj

3. Использование Array.from()

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

kS-1uaQbt9K6zFk4PZWfmnLXHADDnHaVqELf

4. Использование деструктуризации массива

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

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

let [...arrayClone] = originalArray;

Приведенный выше фрагмент создает переменную с именем arrayClone который является клоном originalArray. Вот простая иллюстрация клонирования массива с помощью деструктуризации массива:

aohdaDoLpdH1XJ8Thk5U4JE7u0g89qsaTUcI

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

Вот очень простая демонстрация этого:

изображение

Обратите внимание, что изменение вложенного массива в array1 также изменил вложенный массив array2 и наоборот.

Решение этой проблемы состоит в создании a глубокая копия массива, и это можно сделать несколькими способами.

1. Техника JSON

Самый простой способ создать глубокую копию массива, используя комбинацию JSON.stringify() и JSON.parse().

JSON.stringify() преобразует значение JavaScript в действительную строку JSON, while JSON.parse() преобразует строку JSON в соответствующее значение или объект JavaScript.

Вот простой пример:

изображение-1

Техника JSON имеет некоторые недостатки, особенно если задействованы значения, отличные от строк, чисел и логических значений.

Эти недостатки в технике JSON могут быть в основном связаны с тем, как JSON.stringify() метод преобразует значение в строку JSON.

Вот простая демонстрация этого недостатка в попытке JSON.stringify() значение, содержащее вложенную функцию.

изображение-2

2. Помощник глубокого копирования

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

Вот очень простая и минималистичная функция глубокого копирования, которая называется deepClone:

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

изображение-3

3. Использование библиотек JavaScript

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

Библиотеки JavaScript, как Лодаш и jQuery обеспечивают более надежные функции утилиты глубокого копирования с поддержкой разных типов данных JavaScript.

Вот пример, который использует _.cloneDeep() из библиотеки Лодаша:

изображение-4

Вот тот же пример, но с использованием $.extend() из библиотеки jQuery:

изображение-5

Вывод

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

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

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

Пласкайте и следите

Если эта статья для вас была проницательной, вы можете похвастаться аплодисментами, если вы не против.

Вы также можете подписаться на меня на Medium (Glad Chinda), чтобы получить более глубокие статьи, которые могут быть полезны. Вы также можете подписаться на меня в Twitter (@gladchinda).

Счастливого взлома…

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *