[JavaScript] Кастомные методы для массивов в JS
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Вступление
Всем доброго времени суток. Я думаю, вы заметили, что в массивах в 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
===========
Похожие новости:
- [JavaScript, ReactJS] Новый механизм JSX трансформации в React 17 Release Candidate
- [JavaScript, Программирование, ReactJS] Как использовать Axios в React
- [PHP, Глобальные системы позиционирования, JavaScript, Геоинформационные сервисы] Как высчитать ключи перехода от лобой системы координат к WGS с сантиметровой точностью?
- [JavaScript, HTML, Usability, Accessibility] Вы не знаете как должны работать модальные окна
- [JavaScript, WebGL, Работа с 3D-графикой] Продолжаем чистить память с three.js
- [JavaScript, Программирование, Разработка веб-сайтов] Drag'n'Drop API: пример использования
- [JavaScript, Angular, ReactJS, TypeScript] Простые TypeScript-хитрости, которые позволят масштабировать ваши приложения бесконечно
- [Разработка веб-сайтов, JavaScript, Программирование, VueJS] Vue 3.0 — первый взгляд
- [C, JavaScript, Интернет вещей, Программирование микроконтроллеров, Разработка для интернета вещей] Термостат на ThingJS (beta)
- [JavaScript, Алгоритмы, Программирование] Нестабильная сортировка в JavaScript
Теги для поиска: #_javascript, #_javascript, #_array, #_arrays, #_objects, #_customization, #_javascript
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 23:32
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Вступление Всем доброго времени суток. Я думаю, вы заметили, что в массивах в 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 =========== Похожие новости:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 23:32
Часовой пояс: UTC + 5