Array.from() — JavaScript — Дока

  1. Кратко
  2. Как пишется
  3. Пример
    1. Массив из строки
    2. Массив из Set
    3. Массив из NodeList
  4. Как понять
  5. На практике
    1. Николай Лопин советует

Кратко

Скопировано

Функция Array.from() создаёт новый массив на основе переданного объекта. Объект должен быть либо массивоподобным (как строка или объект arguments), либо итерируемым (как Set или Map).

Как пишется

Скопировано

Функция Array.from() принимает три аргумента, последние два из которых не обязательны:

  • Объект, на основе которого создаётся массив.
  • Функция преобразования элемента перед его добавлением в массив. Работает как метод map().
  • Значение, которое будет использоваться как this в функции из второго параметра.

Возвращает новый массив, составленный из элементов переданного объекта.

Пример

Скопировано

Массив из строки

Скопировано

const arr = Array.from('дока')console.log(arr)// ['д', 'о', 'к', 'а']
          const arr = Array.from('дока')
console.log(arr)
// ['д', 'о', 'к', 'а']

Массив из

Set Скопировано

const uniqueNumbers = new Set()uniqueNumbers.add(1)uniqueNumbers.add(2)uniqueNumbers.add(3)const arr = Array.from(uniqueNumbers)// [1, 2, 3]
          const uniqueNumbers = new Set()
uniqueNumbers.add(1)
uniqueNumbers.add(2)
uniqueNumbers.add(3)
const arr = Array.from(uniqueNumbers)
// [1, 2, 3]

Массив из NodeList

Скопировано

Получить URL из всех ссылок на странице:

const linkElements = document.getElementsByTagName('a')const arrLinks = Array.from(linkElements, function(a) { return a. href })
          const linkElements = document.getElementsByTagName('a')
const arrLinks = Array.from(linkElements, function(a) { return a.href })

Как понять

Скопировано

В JavaScript и браузерных API есть много объектов, которые очень похожи на массив, но не являются им. Объекты могут выглядеть как массив, но не иметь всех методов массива: forEach(), map(), filter() и так далее.

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

Array.from() работает не со всеми объектами. Объект должен обладать одним из двух свойств, чтобы его получилось превратить в массив:

  • Элементы объекта проиндексированы и объект имеет свойство length. Такие объекты называют массивоподобными, потому что именно эти свойства присущи массиву. Этим свойством обладают объекты arguments, NodeList, HTMLCollection.
  • Объект итерируемый, то есть реализует интерфейс Iterable. Этим свойством обладают объекты Set и Map.

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

☝️

При создании массива происходит поверхностное копирование (shallow copy) элементов. Если объект, на основе которого создаётся массив, содержит вложенные структуры данных, то эти вложенные структуры скопированы не будут. При их изменении в объекте изменения будут видны и в полученном массиве.

На практике

Скопировано

Николай Лопин советует

Скопировано

🛠 Если вызвать Array. from() без аргументов, то произойдёт ошибка «TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))».

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

Вместо последовательного вызова Array.from() и .map()

:

const name = 'Mike'const spacedLetters = Array.from(name).map(function (letter) {    return `*${letter}*`})console.log(spacedLetters)// ['*M*', '*i*', '*k*', '*e*']
          const name = 'Mike'
const spacedLetters = Array.from(name).map(function (letter) {
    return `*${letter}*`
})
console.log(spacedLetters)
// ['*M*', '*i*', '*k*', '*e*']

…можно записать один вызов Array.from() со вторым аргументом:

const name = 'Mike'const spacedLetters = Array. from(name, function(letter) { return `*${letter}*` })
          
const name = 'Mike' const spacedLetters = Array.from(name, function(letter) { return `*${letter}*` })

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

🛠 Можно использовать Array.from(), чтобы генерировать последовательности значений без использования классического цикла for.

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

const nums = Array.from({length: 4}, function(value, index) {  // value будет undefined  return index * 2})console.log(nums)// [0, 2, 4, 6]
          const nums = Array.from({length: 4}, function(value, index) {
  // value будет undefined
  return index * 2
})
console. log(nums)
// [0, 2, 4, 6]
Оценка материала

Если вы нашли ошибку, отправьте нам пулреквест!

Во время отправки формы что-то пошло не так. Попробуйте ещё раз?

Предыдущий материал

.length

ctrl

+ alt +

Следующий материал

Array.of()

ctrl + alt +

Видео курс JavaScript Starter. Методы массивов

  • Главная >
  • Каталог >
  • org/ListItem»> JavaScript Стартовый >
  • Методы массивов

Для прохождения теста нужно авторизироваться

Войти Регистрация

×

Вы открыли доступ к тесту! Пройти тест

Для просмотра полной версии видеокурса, онлайн тестирования и получения доступа к дополнительным учебным материалам купите курс Купить курс

Для просмотра всех видеокурсов ITVDN, представленных в Каталоге, а также для получения доступа к учебным материалам и онлайн тестированию купите подписку Купить подписку

№1

Введение

0:28:13

Материалы урокаДомашние заданияТестирование

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

Читать дальше…

№2

Структура кода

0:21:14

Материалы урокаДомашние заданияТестирование

Перед началом изучения синтаксических конструкций, мы узнаем основные правила оформления кода. Начнем с определения понятия инструкция и узнаем, чем инструкции отличаются от комментариев в коде. В этом уроке, вы также научитесь подключать JavaScript к HTML странице и узнаете в чем разница между интерпретацией и компиляцией кода.

Читать дальше…

№3

Переменные и типы данных в JavaScript

0:38:50

Материалы урокаДомашние заданияТестирование

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

Читать дальше…

Строки и преобразование типов

0:28:04

Материалы урокаДомашние заданияТестирование

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

Читать дальше. ..

Операторы

0:39:16

Материалы урокаДомашние заданияТестирование

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

Читать дальше…

Условный оператор if

0:44:53

Материалы урокаДомашние заданияТестирование

Условные конструкции – важная часть любого алгоритма. Без условных конструкций код будет выполняться линейно и одинаково. Если вы хотите сделать так, чтобы действия пользователя могли влиять на последовательность выполнения инструкций, вам нужно научиться работать с оператором if else и узнать особенности работы с типом данных Boolean. Как раз эту задачу решает данный урок.

Читать дальше…

Switch и тернарный оператор

0:22:34

Материалы урокаДомашние заданияТестирование

Оператор if это основа ветвления в коде, но иногда для ветвлений подойдет другая условная конструкция – switch. В этом уроке будут рассмотрены способы использования оператора switch и вы узнаете, как работают такие ключевые слова как case, default и break. Также, в этом уроке будет рассмотрена третья условная конструкция – тернарный оператор. Она не очень часто используется в коде, но в определенных ситуация может сделать код более понятным и коротким.

Читать дальше…

Циклы

0:48:05

Материалы урокаДомашние заданияТестирование

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

Читать дальше…

Массивы в JavaScript

0:36:57

Материалы урокаДомашние заданияТестирование

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

Читать дальше…

Методы массивов

0:28:25

Материалы урокаДомашние заданияТестирование

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

Читать дальше…

Функции. Часть 1

0:51:24

Материалы урокаДомашние заданияТестирование

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

Читать дальше…

Функции. Часть 2

1:00:54

Материалы урокаДомашние заданияТестирование

Функции — это очень важная часть языка JavaScript, поэтому во этом уроке вы продолжите изучение функций и узнаете о том, что такое области видимости. В этом уроке также будут показаны особенности создания переменных с помощью ключевого слова var, которое уже устарело, но все же может встречаться в сценариях. Кроме этого, вы узнаете разные способы определения функций и расширите свои знания, полученные в прошлом уроке. И в дополнение ко всему разберете рекурсию и функции обратного вызова.

Читать дальше…

Объекты. Часть 1

0:35:20

Материалы урокаДомашние заданияТестирование

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

Читать дальше…

Объекты. Часть 2

0:36:56

Материалы урокаДомашние заданияТестирование

В этом уроке будет продолжена тема использования объектов, но будут рассмотрены более продвинутые техники работы с объектами. Вы узнаете, как можно использовать контекст в методах и как создавать фабричные функции, которые позволят наладить создание объектов с одинаковой структурой. Вы научитесь проверять наличие свойств в объекте и работать с ключевым словом in, а также узнаете, что для работы с объектами есть специальный цикл for … in. Кроме этого, в урок вошла важная тема – ссылочные типы и типы значений. Вам не раз пригодятся знания того, как работают разные типы при создании JavaScript сценариев.

Читать дальше…

Следующий курс:

Видео курс JavaScript Базовый — видео курсы ITVDN

ПОКАЗАТЬ ВСЕ

ПОДРОБНЕЕ

ПОДРОБНЕЕ

ПОДРОБНЕЕ

Основные функции массива JavaScript: использование массива копирования JavaScript

Содержание
  • 1. Функции массива JavaScript: основные советы
  • 2. Определение и назначение
  • 3. Описание свойств
  • 4. Методы использования 900 06

Функции массива JavaScript : Основные советы

  • Массив JavaScript — это объект, который может хранить множественных значений .
  • Массивы начинаются с 0 . Первый элемент индексируется как 0, второй — как 1 и так далее.
  • Массивы могут содержать набор любых значений: чисел , слов или объектов .
  • Функции массива JavaScript обеспечивают простой способ их изменения.

Определение и назначение

Функции массива JavaScript разработаны, чтобы помочь вам управлять строками, помещая их в списков похожих элементов. Эти методы встроены в , что означает, что для вашего удобства создание и обработка массивов стандартизированы в JavaScript.

Например, массив с именем cars может состоять из различных производителей автомобилей, таких как Audi, Mazda и Volvo. Следующий код иллюстрирует этот пример и раскрывает синтаксис массива:

Пример

 var cars = ["Audi", "Mazda", "Volvo"]; 

Попробуйте вживую Узнайте на Udacity

Одной из наиболее распространенных функций обработки массивов в JavaScript является метод array. filter() . Он применяется, когда разработчикам необходимо реализовать задачу фильтрации массива JavaScript. Эта функция будет собрать элементы , соответствующие указанному правилу (т. е. сгенерировать список слов, длина которых не превышает трех символов).

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

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

Профессионалы

  • Простота в использовании благодаря принципу обучения на практике
  • Предлагает качественный контент для учащихся от начинающих до продвинутых
Основные характеристики

  • Бесплатные сертификаты об окончании
  • Ориентированы на навыки работы с данными
  • Гибкий график обучения

ЭКСКЛЮЗИВ: СКИДКА 50%

Pros

  • Простой дизайн (без лишней информации)
  • Качественные курсы (даже бесплатные)
  • Разнообразие функций
90 074 Основные характеристики

  • Программы наноградусов
  • Подходит для предприятий
  • Платные Сертификаты об окончании

СКИДКА 15%

Профи

  • Удобная навигация
  • Нет технических проблем
  • Кажется, заботится о своих пользователях
Основные функции

  • Огромное разнообразие курсов
  • 30-дневная политика возврата средств
  • Бесплатные сертификаты об окончании

ОТ 14,99 $

Описание свойств

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

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

Методы использования

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

Например, array.reverse() используется, когда разработчики реализуют задачу JavaScript с обратным массивом. Другими словами, вы можете переключить упорядочить элементов в списке, поставив первый элемент последним, и наоборот.

Другим полезным примером является метод сдвига массива JavaScript ( array.shift() ). Используется, когда необходимо удалить первый элемент в массиве. Кроме того, удаленный элемент будет доставлен как возвращаемое значение .

Метод array.unshift() может показаться похожим на предыдущую функцию, но на самом деле он имеет противоположную функциональность. Неизменяемые массивы означают добавление элемента (или нескольких) в начало массива.

Метод Описание
конкат() Объединяет несколько массивов. Возвращает новый массив.
копировать внутри () Копирует элементы массива из одного индекса в другой.
каждый() Проверяет, все ли элементы массива проходят проверку.
заполнение()Заполняет массив некоторыми значениями.
фильтр() Создает новый массив, используя каждый элемент, прошедший тест.
найти() Создает новый массив со всеми элементами, прошедшими проверку, реализованную предоставленной функцией.
найтиИндекс() Возвращает индекс первого элемента, прошедшего проверку.
для каждого() Выполняет некоторый код для каждого элемента массива.
indexOf() Возвращает индекс указанного элемента.
isArray() Проверяет, находится ли указанный элемент в массиве.
присоединиться() Помещает элементы массива в список строк.
lastIndexOf() Возвращает индекс указанного элемента. Начинает поиск с конца массива.
карта() Выполняет функцию для каждого элемента массива и сохраняет результат в новом массиве.
поп() Удаляет и возвращает последний элемент массива.
нажать() Добавляет новое значение в конец массива и возвращает новую длину массива.
уменьшить() Сокращает значения элементов массива до одного значения.
уменьшитьПраво() Уменьшает значения элементов массива до одного значения (начиная справа).
реверс() Меняет порядок элементов в массиве на обратный.
сдвиг() Удаляет и возвращает первый элемент массива.
срез() Берет часть массива и формирует новый массив.
некоторые() Проверяет, прошел ли тест хотя бы один из элементов.
сортировка() Сортирует элементы массива в алфавитном порядке.
сращивание() Может использоваться для добавления или удаления элементов из массива.
toString() Помещает элементы массива в список строк. Возвращает список.
снять сдвиг() Добавляет новый элемент в массив (в начало) и возвращает старые элементы в исходное положение (увеличивает их индекс на единицу). Возвращает новую длину массива.
значениеOf() Возвращает массив как примитивное значение (обычно строку).

Ускорить обработку массивов JavaScript | Кевин Гадьяни

Фото Криса Овалле на Unsplash

Использование RxJS в качестве библиотеки синхронных преобразователей 18

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

Возьмем эту простую карту , например:

 initialArray 
.map(String)

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

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

Давайте проведем простой тест производительности с 10 миллионами элементов, используя Array.prototype.map :

А затем давайте сравним это с родным циклом for :

Я запускал каждый тест 7 раз и вытягивал средние значения. На моем разогнанном Intel Core i7-4770K наш метод массива усреднил 1281 мс, а наш цикл для усреднил 323 мс. Невероятно, правда? Какое улучшение производительности! А вот шлейфы на это так 10 летней давности. Их сложно написать и труднее обосновать при выполнении сложных преобразований.

Как решить эту почти 300-процентную разницу в производительности, сохранив при этом читабельность нашего кода?

Преобразование — это способ обработки набора логики для каждого отдельного элемента в массиве путем включения его в рекурсивный набор функций редуктора перед выводом значения. Это отличается от того, как работают методы JavaScript Array , потому что каждый элемент в массиве обрабатывается с помощью одного метода map , filter или reduce , прежде чем перейти к следующему, и на каждом этапе пути он создает совершенно новые массивы для размещения этих данных.

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

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

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

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

Преобразователи: эффективные конвейеры обработки данных в JavaScript

Примечание. изучение функционального программирования и композиционного программного обеспечения…

medium. com

Преобразователь выполняет один элемент через набор функций, как и поток RxJS, и это особенно актуально сейчас, когда RxJS реализует шаблон преобразователя с помощью метода pipe и допустимых операторов. чтобы сделать их совместимыми.

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

Во-первых, по какой-то причине RxJS не реализует интерфейс преобразователя, как другие библиотеки преобразователей, поэтому он не совместим с ними из коробки. Ничего страшного, если все равно вы используете только RxJS.

Во-вторых, RxJS полагается на метод подписки , который использует обратный вызов. Методы массива возвращают массивы, а не наблюдаемые, содержащие значение массива. Ну так что ты делаешь? Если вы не используете BehaviorSubject , вы не можете получить синхронное значение, и даже используя его, вы не можете быть уверены, что полученное значение будет таким, как вы ожидаете.

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

Поскольку BehaviorSubject RxJS близок к тому, что нам нужно, давайте посмотрим на его реализацию:

Фу! Это не то, что я хочу делать снова и снова в своей кодовой базе. И не забыть отписаться после подписки? И помнить каждый раз mergeMap ? Ты должно быть разыгрываешь меня.

Также обратите внимание, это даже не работает . Ваше значение — это исходный массив, который вы передали, а не тот, который прошел через конвейер. Вы можете забрать только свои преобразованные значение путем передачи обработчика subscribe , поэтому BehaviorSubject оказался довольно бесполезным.

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

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

Чтобы вернуть значение, нам понадобится что-то вроде этого для нашего наблюдаемого: метод, который в настоящее время не существует в RxJS, это определенно то, что мы могли бы добавить сами в наши собственные проекты.

RxJS имеет метод, аналогичный нашему придуманному execute , который называется forEach , но он разработан аналогично Array.prototype.forEach за исключением того, что вместо возврата undefined он возвращает обещание. Метод promise then ничего не возвращает, но сообщает, когда ваш наблюдаемый объект завершен. В случае ошибки сработает catch . Это довольно изящная установка, но она бесполезна, когда мы пытаемся воспроизвести Array 9. Синхронные операции 0050.

Поскольку мы имеем дело с массивом, в нем нет значений с течением времени. RxJS уже обрабатывает это и завершает наблюдаемое, когда достигает конца списка. Если мы обернем subscribe в нашу функцию execute , мы могли бы вернуть синхронное значение, аналогичное тому, как работает async-await, без необходимости переписывать все приложение.

Вот как я представляю, как мы будем использовать execute :

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

Обратите внимание, что наше значение равно undefined , но через некоторое время мы все еще можем увидеть ошибку о его использовании. Поскольку это асинхронно, мы не можем использовать try-catch, чтобы найти ошибку, но мы можем вывести ее на консоль во время выполнения, чтобы вы знали, что что-то не так.

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

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

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

Я думаю, что автоматическая отмена подписки — это больше, чем вы ожидаете. Таким образом, у вас никогда не будет утечек памяти при использовании выполнить , даже если вы пропустите некоторые полезные ошибки «вы облажались».

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

Этот API можно улучшить, используя из под капотом. Всего на одну вещь меньше для импорта при использовании createExecutableObservable .

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

Это более чистый API по сравнению с циклом для , но намного больше кода, чем оригинальный тест map , поэтому, как и следовало ожидать, это, вероятно, займет намного больше времени. Я имею в виду, что нативный пример — всего лишь один вызов метода по сравнению с этим монстром.

Запустив тест производительности, я был поражен, увидев среднее время 371 мс. Это примерно на 240 % быстрее, чем наш тест map , и только на 13 % медленнее, чем наш цикл for . Я бы сказал, что этого достаточно для меня, но, вероятно, недостаточно, если вы работаете со встроенными системами и имеете очень жесткие ограничения по обработке.

Для удобочитаемости вы бы предпочли написать цикл для или использовать имеющиеся у вас знания о преобразователях RxJS? Что было бы легче поддерживать, особенно когда может пройти еще 3–4 года, прежде чем вы увидите еще один цикл для ?

Реальная история

Преобразователи — это не только персики и сливки. Когда у вас очень небольшое количество элементов, преобразователи работают намного медленнее, чем любое решение. Поиск точки компромисса для большинства машин выходит за рамки этой статьи, но давайте повторим эти тесты производительности с массивом из 3 элементов.

  • Метод массива: 0,33 мс
  • Для цикла: 0,22 мс
  • Преобразователь: 3,06 мс

Внезапно все изменилось. 3 мс для 3 предметов? Это на порядок больше, чем два других решения. Ты шутишь, что ли? Очевидно нет.

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

Именно здесь в игру вступает принцип «правильный инструмент для правильной работы». Если у вас небольшой массив, используйте встроенные методы. Вы теряете преимущества таких замечательных операторов RxJS, как коснитесь (просто используйте фильтр ), но вы получите невероятную скорость и вам не придется на ходу использовать хорошо задокументированные методы Array с шаблонами преобразователя.

Настоящая дилемма возникает, когда вы уже находитесь в конвейере преобразователя RxJS. Когда вы переключаете сопоставление между наблюдаемым и синхронным выполнением массива, что вы используете? Я думаю, это зависит от вашей команды и необходимой обработки. Если вам нужны операторы RxJS, используйте их. Если вы этого не сделаете, вы можете безопасно использовать JavaScripts native Методы массива , если у вас не много элементов или много сложных преобразований.

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

Давайте воспользуемся генератором из моей предыдущей статьи о Lossless Backpressure в RxJS , но без обработчика асинхронного противодавления:

Круто, правда? Единственная причина, по которой это работает, заключается в том, что RxJS проходит через все значения генератора, создает и массив и проталкивает значения одно за другим через конвейер.