Русский
Русский
English
Статистика
Реклама

Из песочницы Кастомные методы для массивов в JS

Вступление


Всем доброго времени суток. Я думаю, вы заметили, что в массивах в JS довольно много хороших встроенных методов. Однако, зачастую, даже их не хватает. Например: мне бы хотелось проверять массивы на пересечение. Конечно, я могу писать так:

checkIntersections(arr1, arr2)

но гораздо удобнее было бы писать вот так:

arr1.checkIntersections(arr2)

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

arr1 = deleteDuplicates(arr1);

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

Исследуем массивы


Чтобы понять, как нам взаимодействовать с массивами. Мы для начала должны понять, что из себя представляет сам массив. Для этого давайте выведем его в консоль:

let arr = ["I", "love", "JS"]; console.log(arr);

Вот, что мы увидим:



Как видите, консоль показывает нам, что это массив с 3-я элементами. Но также мы видим, что рядом с ним есть кнопка раскрытия (треугольник). Если мы нажмем на нее, то увидим следующее:



Ничего не напоминает? Это же объект! Мы видим, что его свойствами являются числовые ключи и length. Поэтому мы и записываем: array[0]. Мы обращаемся к свойству объекта array с именем 0. Квадратные скобки нужны, поскольку это имя этого свойства представлено числом. А что это за Array(3)? Это строка показывает, экземпляром какого объекта является массив, то есть, с помощью какого класса он создан. Значит, все массивы это экземпляры класса Array. Обладая этими знаниями, давайте попробуем записать какой-нибудь свой метод.

Добавляем новый метод


Давайте сделаем метод, который будет проверять, есть ли в нашем массиве элемент переданный аргументом. Для этого в цикле переберем все элементы нашего массива и вернем true при обнаружении совпадения. Если по завершении цикла совпадение не будет обнаружено вернем false. Назовем этот метод checkElement. Итак, чтобы добавить его к массиву, обратимся к свойству prototype класса Array.

Array.prototype.checkElement = function(e) {};

Теперь пройдемся циклом по всем элементам. Сделать это очень просто:

for (var i = 0; i < this.length; i++) {this[i];}

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

if (this[i] === e) {    return true;}

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

Array.prototype.checkElement = function(e) {for (var i = 0; i < this.length; i++) {if (this[i] === e) {return true;}}return false;};

Давайте проверим его в действии.

console.log(arr.checkElement("I"));console.log(arr.checkElement("not"));

Все работает, но если бы все было так просто, было бы подозрительно.

Исправляем появившуюся ошибку


Давайте попробуем сделать следующее: переберем наш массив с помощью цикла for in.

for (let i in arr) {    console.log(i);}

Как видите, произошел косяк: JS стал видит наш новый метод в этом цикле. Разумеется, при использовании такого цикла в коде, это может привести к ошибке. Но почему JS видит наш метод, но не видит например метод push? Давайте вновь обратимся к консоли и выведем все методы нашего массива. Вот так:

console.log(arr.__proto__);

Вот, что мы увидим:



Как видите: встроенный методы отобразились более тусклым текстом чем наш метод. Это означает, что эти методы обладают особым свойством, которое делает их невидимыми для цикла for in. Но что это за свойство? Если мы прочитаем документацию о технологии Object.defineProperty на MDN (вот она), то заметим там параметр enumerable. Как мы можем узнать, если его значение установить как false, цикл for in не будет видеть свойство с этим параметром. Давайте так и сделаем, а чтобы не писать миллион одинаковых инструкций, применим ее ко всем методам.
Вот так:

Object.keys(Array.prototype).forEach(method => {Object.defineProperty(Array.prototype, method, {enumerable: false,});});

Здесь мы получаем массив ключей нашего объекта Array.prototype и, с помощью Object.defineProperty, делаем их невидимыми для цикла for in. Давайте проверим теперь.

console.log(arr.checkElement("I"));for (let i in arr) {console.log(i);}

Прекрасно! Все работает так, как мы и ожидали.

Итог


Итак, вот код, который у нас получился.

Array.prototype.checkElement = function(e) {for (var i = 0; i < this.length; i++) {if (this[i] === e) {return true;}}return false;};Object.keys(Array.prototype).forEach(method => {Object.defineProperty(Array.prototype, method, {enumerable: false,});});

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

Я думаю, таким же методом можно изменять и другие технологии в JS. Главное понять как они устроены.
Источник: habr.com
К списку статей
Опубликовано: 04.10.2020 00:22:46
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Javascript

Array

Arrays

Objects

Customization

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru