Расширение массивов, замораживание объектов, переопределение методов нечистых массивов и т. Д.

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

Расширение массива

Начнем с расширения класса Array и добавления простого нового метода.

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

Метод first возвращает первый элемент из массива.

За сценой создается объект ExtendedArray.prototype, содержащий новый метод и наследуемый от объекта Array.prototype.

Метод Array.of создает новый экземпляр Array, содержащий все переданные аргументы. Например, ниже мы можем увидеть, как создать массив, содержащий значения 1, 2 и 3.

const arr = Array.of(1, 2, 3);
//[1, 2, 3]

Аналогичным образом мы можем использовать метод ExtendedArray.of в новом классе для создания нового расширенного массива.

const arr = ExtendedArray.of(1, 2, 3);
//ExtendedArray(3) [1, 2, 3]

Теперь можно вызывать метод first в новом расширенном массиве.

arr.first();
//1

Если мы проверим новый объект, мы можем заметить, что «скрытое» свойство __proto__ указывает на ExtendArray.prototype , которое также имеет свойство __proto__, относящееся к Array.prototype.

Вызов стандартных методов массива

Следующий вопрос - какие массивы возвращаются при использовании стандартных методов массива, таких как map или filter.

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

Рассмотрим тривиальную функцию отображения, удваивающую число.

function double(no){
  return no * 2;
}

Вот результат вызова метода map для расширенного массива. Он по-прежнему возвращает новый расширенный массив, который нам нужен.

const newArr = arr.map(double);
//ExtendedArray(3) [2, 4, 6]

В новом расширенном массиве мы можем вызвать метод first.

newArr.first();
//2

Делаем массив неизменяемым

Неизменяемый массив - это массив, который после создания не может быть изменен. Вызов методов на нем должен создавать новые массивы.

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

const arr = ExtendedArray.of(...args);
Object.freeze(arr);

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

Массивы эмулируются с помощью объектов, поэтому Object.freeze работает и с массивами.

После замораживания массива мы не можем вызывать нечистые методы, такие как push или pop. В замороженном массиве мы можем вызывать только чистые методы массива, которые не изменяют текущий массив.

arr.push(1);
//Cannot add property 0, object is not extensible

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

Как только мы создадим массив с помощью новой утилиты ExtendedArray.immutableOf, мы больше не сможем вызывать методы нечистого массива.

Переопределение методов для возврата замороженных массивов

Массив создается с помощью immutableOf. Утилита замораживается, но после использования стандартного метода, такого как map, мы снова получаем расширенный массив, который можно изменить. Рассмотрим приведенный ниже код, создающий расширенный массив и затем использующий для него метод map.

Как видите, мы можем вызвать нечистый метод push в массиве после использования метода map.

Нам нужно переопределить метод map в расширенном массиве, чтобы он возвращал замороженный массив. Вот как мы можем это сделать.

Ключевое слово super в методе класса дает доступ к функциям родительского прототипа объекта.

Теперь при попытке вызвать нечистый метод типа push после использования map мы получаем ошибку.

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

Текущий sort метод нечист. Мы можем создать новый, создав новый отсортированный замороженный массив.

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

Вот полный расширенный массив, содержащий также метод last.

После создания нового расширенного массива мы можем использовать новые чистые методы.

Все новые методы расширенного массива (filter, map, sortBy и add) возвращают замороженный расширенный массив.

Последние мысли

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

Мы можем расширить стандартный класс Array и добавить новые методы или переопределить существующие.

Метод of в новом расширенном классе создает новый расширенный массив.

Стандартные методы массива, такие как filter и map, вызываемые для расширенного массива, возвращают расширенные массивы.

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

Спасибо за прочтение.