5 малоизвестных особенностей jQuery-методов Javascript


Оглавление (нажмите, чтобы открыть):

Нативные эквиваленты jQuery методов — Часть 1: Выборка DOM элементов

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

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

Этот пост будет посвящен множеству методов для выбора DOM элементов.

Получить элемент по его ID

jQuery
Нативный JS

Обратите внимание, что jQuery метод возвращает объект, в то время как нативные версии возвращают узел DOM дерева.

Получить элементы по имени тега (tagName)

jQuery
Нативный JS

Получить элементы по имени класса (className)

jQuery
Нативный JS

Обратите внимание, что, как и jQuery $() метод, querySelector и querySelectorAll оба принимают строковой CSS3 селектор.

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

Это позволит начать поиск непосредственно из parent узла и вернуть все дочерние элементы с именем класса ‘child-class’

Итак, какой из них использовать?

Хорошо, у нас есть getElementsByTagName , getElementsByClassName и querySelectorAll , так какой из них использовать?

Хоть метод querySelectorAll и является более современным подходом и ближе к jQuery методу $(selector) , так как он позволяет использовать в широком диапазоне CSS3 селекторы, есть одно главное различие, которое может вернуться и укусить вас в зад, если вы не знаете этого.

Метод querySelectorAll как и jQuery $(selector) метод, будет возвращать статический NodeList , тогда как getElementsByTagName и getElementsByClassName будут возвращать живой NodeList .

Хорошо, так в чем отличие?

Подумайте о статическом NodeList как снимок DOM дерева, когда метод querySelectorAll был вызван. Все что вы делаете с DOM после вызова метода querySelectorAll не будет отображено в NodeList при возврате. В то время как живой NodeList вернувший getElementsByTagName и будет getElementsByClassName .

Почему это так важно?

Возьмем следующий список элементов:

Давайте получим элементы с помощью метода querySelectorAll

Теперь посчитаем эти элементы:

Добавим новый элемент в список:

Теперь давайте снова считать элементы:

Ой, что случилось? Теперь у нас есть 5 элементов в списке, но второй счетчик все еще показывает 4 элемента!

В этом и заключается суть статического NodeList , существенное отличие которое вам нужно знать при использовании querySelectorAll перед getElementsByTagName и getElementsByClassName . Так как оба последние методы возвращают живой NodeList , пересчет при второй попытки должно было вернуть 5. На самом деле, не важно какое количество элементов вы добавили или удалили, последние методы всегда будут отображать изменения.

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

Рабочий пример приведенный выше можно найти по этой ссылке: codepen.io/Mobius1/pen/jMjjZd.

Дополнительные селекторы

Получить первый элемент

jQuery
Нативный JS

Помните, что вы можете заменить document с DOM узлом, чтобы сделать поиск более эффективным.

Также отметим, что querySelector возвращает первый подходящий Element узла, в то время как querySelectorAll вернет NodeList .

Получить дочерние узлы элементов

jQuery
Нативный JS

Не используйте метод childNodes если не знаете что делаете, или вы должны поддерживать IE firstChild имеет аналогичные подводные камни как childNodes .

Помните, что метод jQuery вроде $() , querySelector и querySelectorAll оба поддерживают сложные CSS3 селекторы, поэтому так же могут быть использованы ниже:

В случае с jQuery, есть множество способов получения желаемого узла в приведенном выше примере, таким образом просто выберите тот, который соответствует вашим потребностям, но следует отметить что (в зависимости от используемого браузера) старые getElementsByTagName и getElementsByClassName методы могут быть гораздо быстрее, чем новые родные и jQuery методы: запустить тест

Получить последний дочерний элемент

jQuery
Нативный JS

Как и c firstChild и childNodes , lastChild следует использовать только если вы собираетесь поддерживать IE null , если MyElement является последним потомком его родителя.

Получить предыдущий элемент

jQuery
Нативный JS

Нативные методы будут возвращать null , если MyElement является первым потомком его родителя.

nextSibling и previousSibling методы должны рассматриваться так же, как и childNodes , firstChild и lastChild , для их возврата узлов за исключением HTMLElements.

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

Нет нативной альтернативы?

Обход DOM дерева может быть непростой задачей (особенно для новичков) и к счастью jQuery имеет много полезных методов что бы помочь. Однако не все jQuery методы имеют родной эквивалент.

Получить ближайший элемент вверх по DOM дереву (предка) соответствующий селектору

jQuery
Нативный JS

Несмотря на наличие родной версии jQuery метода closest() , она экспериментальная, и поэтому не должна использоваться на продакшене.

Дополнительно к прочтению: Element.closest()

Давайте создадим наш собственный вместо этого.

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

Вот и все на сегодня. В следующем посту мы будем рассматривать нативные методы jQuery attr() , prop() , addClass() , hasClass() , removeClass() и методы «полифилов» для старых браузеров.

JavaScript Методы объекта

Пример

Ключевое слово this

В определении функции это относится к «владельцу» функции.

В приведенном выше примере это объект Person , который «владеет» функцией » функция».

Иными словами, this. имя означает свойство » имя » этого объекта.

Подробнее об этом ключевом слове в JS это ключевое слово.

Методы JavaScript

Методы JavaScript — это действия, которые могут выполняться над объектами.

метод JavaScript — это свойство, содержащее Определение функции.

Свойство Значение
firstName John
lastName Doe
age 50
eyeColor blue
fullName function()

Методы — это функции, хранящиеся в качестве свойств объекта.

Доступ к методам объектов

Доступ к методу объекта со следующим синтаксисом:

Как правило, в качестве метода объекта Person будет описываться метод (), а в качестве свойства — свойство.

Свойство свойства будет выполняться (как функция) при вызове с ().

В этом примере обращается к методу () метода () объекта Person:

Пример

При доступе к свойству » свойство» без () он вернет Определение функции:

Пример

Using Built-In Methods

В этом примере используется метод toUpperCase () объекта String для преобразования текста в верхний регистр:

The value of x, after execution of the code above will be:

Добавление метода к объекту

Добавить новый метод к объекту очень просто:

JavaScript — урок 5. JQuery

В этой теме 0 ответов, 1 участник, последнее обновление Васильев Владимир Сергеевич 1 год, 1 месяц назад.

Обзор JQuery

Главным удобством библиотеки является возможность выбора HTML элементов по css селекторам, и работы с ними как с одним объектом. Т.е. изменить стиль нескольких объектов можно вызовом одного метода без циклов. Есть поддержка ajax, несколько визуальных эффектов, собственные виджеты (элементы управления) пользовательского интерфейса как закладки.

В ужатом виде занимает от 30кб.

Скачать JQuery можно с домашнего сайта библиотеки. Для кракткости можно переименовать файл, например jquery-1.2.5.pack.js в jquery.js.

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

Файл jquery ui в полном объеме довольно большой (почти 200кб). В скаченном вами архиве есть папка development-bundle/ui, где JQuery UI хранится по частям (в не сжатом виде). Таким образом, для сокращения времени загрузки страницы можно подключать только нужные части jquery ui.

Чтобы виджеты выглядели как в примерах на официальном сайте, не забудьте подключить стили. Они также доступны по раздельности, что облегчает редактирование. На сайте jqueryui.com доступны различные цветовые темы.

Пример использования JQuery

Принцип работы следующий. Вызываем функцию $, возвращающую объект JQuery.
Аргумент этой функции задает, с какими объектами будет работать созданный JQuery:

  • существующий dom объект;
  • css селектор версий 1-3 (поддерживаемый список);
  • обычный html текст, который можно будет добавить к существующим объектам.

После этого вызываем методы JQuery, которые будут применяться ко всем отобранным объектам.
Основные методы:

  • html() — получить значение innerHTML первого объекта;
  • html(«…») — установить значение innerHTML всех объектов;
  • text() — получить содержимое всех объектов в виде чистого текста (без тегов);
  • text(«…») — вставить текст в объекты, спец символы будут заменены на & последовательность;
  • val()/val(«…») — получить/установить значение управляющего элемента как текстовое поле;
  • css(«stylename») — возвращает значение стиля stylename первого объекта;
  • css(<…>) — устанавливает стили всем объектам, стиль задается ассоциативным массивом, где
    ключ имя стиля, значение — значение стиля;
  • css(«stylename»,»val») — установить значение стиля всем объектам.

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


Ниже приведен пример использования библиотеки. При клике на надписи «меняем стиль» меняется стиль
надписи «Hello World». Текст в левой ячейке таблицы, также генерится средствами библиотеки
по innerHTML правой ячейки. Единственно, в IE элемент span содержит атрибут
типа jQuery1238508360187=»2″.

Hello World

Hello World
Hello world Hello world

меняем стиль

стиль элемента JQuery

Для работы со стилями элементов определены следующие методы:

  • css(‘name’) — возвращает значение стиля name первого элемента;
  • css(properties) — устанавливает всем элементам стиль, заданный в виде массива свойств

позиция

Методы для работы с позицией элементов

  • offset() — возвращает позицию первого элемента в пикселях относительно документа,
    значение указывается в виде объекта со свойствами top и left (т.е. Object);
  • position() — позиция элемента в виде Object относительно родительского элемента;
  • scrollTop() — смещение верхней прокрутки первого элемента;
  • scrollTop(val) — установить смещение верхней прокрутки всех элементов;
  • scrollLeft() — смещение левой прокрутки первого элемента;
  • scrollLeft(val) — установить смещение левой прокрутки всех элементов;

размеры

  • height() — высота в пикселях первого элемента;
  • height(val) — устанавливает высоту всех элементов;
  • width() — ширина в пикселях первого элемента;
  • width(val) — устанавливает ширину всех элементов;
  • innerHeight() — внутренняя высота (т.е. без рамки, но включая внутренний отступ (padding));
  • innerWidth() — внутренняя ширина;
  • outerHeight(margin) — внешняя высота (т.е. с рамкой и внутрениим отступом), если аргумент
    margin равен true, то внешние отступы также будут добавлены;
  • outerWidth(margin) — внешняя ширина.

пример

Работа с html кодом в JQuery

Общие методы

  • html() — html содержимое первого элемента (т.е. innerHTML).
    Не работает с xml документами, но работает с xhtml;
  • html(val) — устанавливает html содержимое для всех элементов;
  • text() — получить соединенный текст всех элементов;
  • text(val) — установить текстовое содержимое всех элементов.

вставка внутри элемента

  • append(content) — добавить в конец содержимого каждого элемента;
  • appendTo(selector) — добавить выбранные элементы в конец каждого элемента из
    указанного множества элементов;
  • prepend(content) — добавить в начало содержимого каждого элемента;
  • prependTo(selector) — добавить выбранные элементы в начало каждого элемента
    из указанного множества элементов.

вставка вне элемента

  • after(content) — вставить после каждого элемента;
  • before(content) — вставить перед каждым элементом;
  • insertAfter(selector) — вставить все элементы после каждого элемента из указанного множества
    элементов;
  • insertBefore(selector) — вставить все элементы перед каждым элементом из указанного множества
    элементов.

оберточные методы

Под «обернуть» понимается вставка до и после чего-либо.

  • wrap(html) — обернуть каждый элемент указанным html кодом;
  • wrap(elem) — обернуть каждый элемент указанным DOM элементом (т.е. объектом типа Element);
  • wrapAll(html) — обернуть выбранное множество элементов указанным html кодом;
  • wrapAll(elem) — обернуть выбранное множество элементов указанным DOM элементом;
  • wrapInner(html) — обернуть содержимое каждого элемента указанным html кодом;
  • wrapInner(elem) — обернуть содержимое каждого элемента указанным DOM элементом.

замена

  • replaceWith(content) — заменить все элементы указанным html или DOM элементом;
  • replaceAll(selector) — заменить выбранными элементами все элементы из указанного
    множества.

удаление

  • empty() — удаление из каждого элемента всех дочерних элементов;
  • remove([expr]) — удаляет все или отфильтрованные аргументом expr элементы из DOM. Как
    объекты JavaScript они продолжают существовать, так что их можно использовать дальше.

копирование

  • clone() — создает копии выбранных DOM элементов и выбирает их;
  • clone(bool) — аналогично предыдущему, но если аргумент true, клонируются и
    обработчики событий.

События в JQuery

Ниже представлены методы JQuery устанавливающие обработчики событий всем выбранным элементам.
Имена большинства методов образуются удалением on из имени соответствующего события. Например, onclick->click().

  • ready(fn) — готовность документа;
  • load(fn) — загрузка документа;
  • unload(fn) — выгрузка документа;
  • blur(fn) — потеря фокуса;
  • focus(fn) — получение фокуса;
  • click(fn) — одинарный клик мышью;
  • dblclick(fn) — двойной клик мышью;
  • mousedown(fn) — нажатие клавиши мыши;
  • mouseenter(fn) — вход мыши;
  • mouseleave(fn) — уход мыши;
  • mousemove(fn) — движение мыши;
  • mouseout( fn ) — уход мыши;
  • mouseover(fn) — вход мыши;
  • mouseup(fn) — обработчик отжатия кнопки мыши;
  • keydown(fn) — нажатие клавиши;
  • keypress(fn) — использование клавиши;
  • keyup(fn) — отжатие клавиши;
  • error(fn) — ошибка;
  • change(fn) — изменение;
  • select(fn) — выбор;
  • resize(fn) — изменение размеров;
  • scroll(fn) — прокрутка;
  • submit(fn) — отсылка данных.

Учебник jQuery для новичков от Трепачёва Дмитрия

Учебник JavaScript

Практика

Работа с DOM

Практика

Некоторые продвинутые вещи

Рекомендованное ES6

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

Регулярки

Разное

Работа с канвасом

Практика

  • урок исключен (мало материала), по аяксу скоро будет отдельный учебник (много материала)
    Работа с
    AJAX в JavaScript
    Работа с
    AJAX + PHP

Контекст

Drag-and-Drop

  • Урок №
    Введение
    в ООП в стиле ES6
  • Урок №
    Основы
    работы с ООП
  • Урок №
    Наследование
    классов в JavaScript
    Продвинутая работа
    с классами на JavaScript
  • Урок №
    Применение
    ООП при работе с DOM
  • Урок №
    Практика
    по ООП в JavaScript
  • Тут скоро будут еще уроки
    по функциональному и прототипному
    стилю ООП.

Практика по ООП

Ваша задача: посмотрите, попробуйте повторить.

Практика

Promise ES6

Библиотека jQuery

Тк. jQuery устаревает, объявляю эти уроки не обязательными и выношу в конец учебника (так по уровню уроки середины учебника, если что). В перспективе переедет в отдельный учебник по jq.

В данном уроке мы с вами начнем изучать библиотеку jQuery. Для работы с ней вы должны владеть хотя бы минимальными навыками JavaScript.

Если вы не изучали предыдущие уроки (но умеете что-то делать на JavaScript) — можете их пока не смотреть, дальше по тексту будут раскиданы ссылки на те темы, которые нужно будет знать к конкретному уроку.

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

Что такое jQuery?

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

Сравните два кода, которые делают одно и тоже — первый на чистом JavaScript, а второй — на jQuery:

Код jQuery выглядит намного компактнее и проще для написания.

Сравните еще два кода: в первом мы получаем все элементы с классом .www и ставим им красный цвет текста с помощью чистого JavaScript, а во втором — на jQuery:


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

Подключение jQuery

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

После подключения можно начинать писать код с использованием этой библиотеки.

Видео для тех, кто ничего не понял

Если вам все равно не понятно, что, как и куда подключать — смотрите следующее видео:

Здесь скоро появится видео по подключению jQuery.

Начало работы с jQuery

Работа с библиотекой jQuery осуществляется с помощью универсальной функции $, которая для краткости состоит всего лишь из одного символа.

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

Чаще всего с помощью доллара $ получают группу HTML элементов по CSS селектору.

Давайте получим все элементы с классом .www:

А теперь получим только абзацы с классом p.www:

А теперь получим элемент с id, равным www:

Как вы видите, используются обычные CSS селекторы, подобно методу querySelectorAll. Только querySelectorAll появился гораздо позже, чем jQuery, и обладает меньшими возможностями (зато работает быстрее).

Наборы jQuery

Обратите внимание на переменную elems:

В нее запишется группа выбранных элементов, так называемый набор элементов jQuery.

Вы можете одновременно менять все элементы набора jQuery (в отличие от querySelectorAll никаких циклов не требуется).

В принципе, переменная elems чаще всего и не нужна, так как jQuery позволяет применять полезные функции прямо к набору, в виде методов.

К примеру, вот так мы получим все элементы с классом .www и поставим им красный цвет:

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

Давайте получим все элементы с классом .www, поставим им красный цвет, и сменим их текст на ‘новый текст’:

5 полезных методов jQuery API, о которых вы могли не знать

В статье я расскажу о пяти методах jQuery, которые я нашел для себя полезными и о которых, по моим наблюдениям, мало кто знает.

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

jQuery.grep()

jQuery.grep(array, function(elementOfArray, indexInArray) [, invert]) — как можно догадаться с названия, метод фильтрует элементы массива полагаясь на результат функции (оригинальный массив не изменяется). У jQuery также есть похожий метод .filter() который служит для фильтрации набора найденных элементов.

Пример

Нужно выбрать из массива только числа кратные 3:

.map( callback(index, domElement) ) — метод полезен тем, что дает возможность без написания циклов сделать преобразования над выбранными элементами или массивом (для массивов нужно использовать jQuery.map() ).
Если функция возвращает null или undefined, то элемент будет проигнорирован.

Пример

Выведем адреса всех ссылок на странице:

jQuery.proxy()

jQuery.proxy( function, context ) — может быть полезным, если нужно передать callback но установить для него свой контекст (значение переменной this ).

Пример

.prop( propertyName, value ) — этот метод появился в версии 1.6 и я использую его примерно с того же времени. Но решил упомянуть здесь потому, что многие ошибочно используют метод .attr() для доступа к свойствам элементов и модификации их значений.
Дело в том, что с версии 1.6 .attr() работает непосредственно с атрибутом элемента и в некоторых случаях результат не совсем ожидаемый.
Например, если мы хотим узнать состояние чекбокса, то .attr() может выдать его значение по умолчанию (которое видно в исходниках HTML страницы). В этом случае нам нужно использовать метод .prop() — он вернет текущее значение свойства элемента.

Пример

Инвертируем все чекбоксы на странице:

.serializeArray()

.serializeArray() — очень простой способ сеарилизации данных формы в виде массива или строки (в этом случае используйте .serialize() ). Метод возвращает массив, который потом например можно через ajax передать на сервер.

5 jQuery-фич, перешедших в нативный JavaScript

Сегодня у нас рассказ пойдет про jQuery и о том влиянии, которое он оказал на развитие современных браузеров. А рассмотрим мы это влияние на примере фич, которые, фактически, перекочевали из него в нативный JavaScript.

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

Фича #1: querySelector

Кто пользовался jQuery, тот знает, что если в функцию $, являющуюся коротким синонимом для более длинной переменной jQuery, передать строчку с любым валидным CSS-селектором, то на выходе мы получим коллекцию из найденных элементов, соответствующих этому селектору. Это будет нативная JS-коллекция, обернутая в jQuery-оболочку, у которой на прототипе есть полезные методы и свойства, которые, собственно описаны в документации библиотеки.

Конечно функция $ намного более функциональна, ведь она позволяет создавать DOM-ноды и делать другие полезные штуки. Но для нас интересно то, что с некоторых пор в нативном JS имеются не только исконные, содержащиеся на document методы getElementById, getElementByClassName и остальные, а еще и querySelector с querySelectorAll.

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

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

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

Или еще короче, в стиле ES6:

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

Использовать такие функции становится очень удобно:

Вот это заселектит нам кнопку и сохранит в переменную myBtn.

Если это не пересекается с другими библиотеками, то можно вовсе переименовать qSA в символ доллара и будет «типа jQuery» =)

Фича #2: />

classList имеет внутри себя каждая нода браузера. Я заселектил элемент и вижу у него classList. Кстати, в консоли инструментов разработчика в Chrome обратиться к последнему выделенному элементу в DOM-дереве можно через $0.

Подробно про инструменты Хрома я рассказывал в другом видео:

Пока список классов пуст, но если вызвать метод add, то класс можно добавить. С помощью remove его можно удалить, а через toggle можно его переключать — если был, то удалится и наоборот.

Все это произросло из jQuery-методов addClass, removeClass и toggleClass — как видите, названия тоже перекочевали.
У classList есть еще полезные методы — рекомендую вам с ними познакомиться, потому что операции с нодами это то, что в JavaScript делают наверное чаще всего и умение минимумом кода достигнуть максимум результата это полезный навык.

Фича #3: closest

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

Фича #4: fetch

Вы наверное слышали про AJAX, который является совокупностью подходов для выполнения асинхронных (и если надо, то синхронных) HTTP-запросов. Для этого в браузерах существовал издавна объект XMLHttpRequest или сокращенно XHR. Пользоваться им в чистом виде достаточно проблематично и некрасиво с точки зрения оформления кода, поэтому программисты всегда писали обертки, вызывающие нативные функции. Подобные тому, что я привел для querySelector.

Вот так выглядит простейший код с XHR-запросом:

Согласитесь, громоздко. А вот пример запроса, но с помощью jQuery-функции ajax:

Однако в современных браузерах появился fetch, который выглядит вот так для того же запроса:

Не правда ли синтаксис очень похож? Тут ясно откуда растут ноги. Fetch, кстати работает внутри все равно используя тот самый XHR, но так ведь писать код намного удобнее и компактнее! Кстати, удобство в fetch доситигается за счет промисов.

Фича #5: Promise и Deferred

Про промисы в последнее время говорят очень много. Да и не только говорят, а используют при написании кода, потому что с приходом ES6 (он же ES2015), промисы стали частью нативного API браузерного JS. Короче говоря, о промисах вы скорее всего слышали, но вероятно не знали, что эта концепция намного старше JavaScript и не относится исключительно к нему.

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

Другие языки также имеют свою реализацию промисов, например, Ruby, Python, Closure и другие. Но нас интересует сфера JS и jQuery.

В jQuery есть объект Deferred, как раз реализующий конкретную спецификацию промисов, о чем недвусмысленно сказано в документации.

Давайте посмотрим на простейший пример того, как работает Deferred:

Сначала я определяю функцию deferredOperation, внутри которой создаю Deferred-объект (изначально он в состоянии неопределенности или ожидания — pending) и говорю что через полторы секунды он должен будет перевестись в состояние resolved — успешно разрешен, или в состояние rejected — то есть отменен.
И этот экземпляр Deferred я из функции возвращаю.

Обращаю внимание, что return dfd выполнятся до того, как setTimeout отсчитает свои полторы секунды. То есть он сработает асинхронно, или иными словами параллельно синхронному коду. Внутри setTimeout генерируется дробное случайное значение от 0 до 1 и если получившееся больше 0.5, то на dfd вызываем функцию resolve, тем самым переводя промис в состояние resolved. Ну или в rejected с помощью метода reject, если Math.random() нам нагенерил число меньше 0.5.

Далее я возвращенное значение из выполненной функции deferredOperation присваиваю промежуточной переменной result. А затем говорю, что если dfd переведется в состояние resolved, то выполнится тот колбэк, что внутри done. А иначе — тот, что внутри fail.

Получается что мы можем расставить наши done и fail где угодно и они сработают как только Deferred разрешится в какое-то состояние. Мы ведь не знаем сколько например займет сетевой запрос — это зависит от задержек в сети. Поэтому такой синтаксис очень удобен в этом случае, как собственно и в любом другом случае, когда мы не знаем сколько точно займет та или иная операция.

На самом деле, уже рассмотренная нами jQuery-функция ajax также возвращает Deferred-объект. Так что можно будет сделать что-то когда запрос завершится. Совершенно по аналогии с предыдущим примером. В нем эмулятором задержки был setTimeout, кстати говоря.

А здесь задержка в запросе действительно будет непредсказуема:

Здесь мы делаем ajax-запрос с помощью jQuery и так как подразумевается что Deferred возвращется, то по цепочке можно выполнить done и fail. Но можно, как и до этого, присвоить результат запроса в промежуточную переменную и потом вызывать done и fail где-то дальше в коде.

Итак, сейчас я вам очень коротко показал как устроен Deferred в jQuery, хотя многие моменты мы не затронули, инчае бы все затянулось.

Браузерный же Promise это тоже конкретная реализация спецификации. В новых браузерах это доступно «искаропке», а для более старых можно подключить полифилл.

Вот так работают промисы в сегодняшнем нативном JavaScript:

Тут чуть иначе. мы создаем новый промис, в который пробрасываются функции-переключатели состояния промиса. То есть внутри мы в зависимости от значения вызываем их и переключаем промис в одно из двух состояний.

Далее then будет срабатывать если промис разрешается успешно (если был вызван resolve), и catch, если промис был отменен через вызов rejected.

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

А вот пример с fetch:

Здесь мы делаем запрос на фейковый API, затем ответ интерпретируем как JSON и выводим результат в консоль. В противном случае сработает catch и мы выведем ошибку.

Fetch возвращет Promise, который умеет делать then и catch. Совершенно по аналогии с Deferred, который умеет делать done и fail. Так что можно сказать, что из jQuery это перекочевало в нативный JS.

jQuery — Методы для работы с набором элементов

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

Виды методов jQuery для работы с набором элементов

Библиотека jQuery содержит методы, которые предназначены для выполнения различных операций над набором элементов. Эти методы сгруппированы в 3 категории:

  • Методы для фильтрации элементов текущего набора: eq(), first(), last(), slice(), filter(), has(), is(), map(), not().
  • Методы, осуществляющие поиск элементов в DOM-дереве: children(), closest(), find(), next(), nextAll(), nextUntil(), offsetParent(), parent(), parents(), parentsUntil(), prev(), prevAll(), prevUntil(), siblings().
  • Категория, в которой собраны методы, выполняющие различные действия: add(), addBack(), contents(), end(), not().

Методы для фильтрации элементов текущего набора

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

.eq(index) — осуществляет выбор элемента с указанным индексом ( index ) из текущей выборки.

.first() — осуществляет выбор первого элемента из текущей выборки.

.last() — осуществляет выбор последнего элемента из текущей выборки.

.slice(startIndex[,endIndex]) — осуществляет выбор из текущего набора только тех DOM-элементов, которые имеют индексы в пределах указанного диапазона (от startIndex до endIndex ).

.filter(выражение) — осуществляет выбор элементов из текущего набора в соответствии с указанным выражением ( selector ).

.has(selector) — осуществляет выбор только тех элементов из текущей выборки, которые имеют хотя бы один из элементов, заданных с помощью селектора (или в виде DOM-коллекции), в качестве своего потомка.

.map(функция) — возвращает объект jQuery, состоящий из результатов, которая возвратила указанная в качестве параметра функция для каждого элемента текущего набора.

.is(выражение) — проверяет каждый элемент текущего набора в соответствии выражением, указанным в качестве параметра данного метода и возвращает true или false . Данный метод возвращает значение true , если хотя бы один из элементов исходного набора соответствует выражению, указанного в качестве параметра данного метода.

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


Методы, осуществляющие поиск элементов в DOM-дереве

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

.next() . Данный метод выполняет следующее: он для каждого элемента текущего набора осуществляет поиск следующего за ним элемента, который должен являться по отношению к нему сиблингом (siblings). Метод .next() в качестве своего результата — возвращает объект jQuery, состоящий из найденных элементов.

.nextAll() — Данный метод выполняет следующее: он для каждого элемента текущего набора осуществляет поиск всех следующих за ним элементов, которые по отношению к нему являются сиблингами (siblings). Метод .nextAll() в качестве своего результата — возвращает объект jQuery, состоящий из найденных элементов.

.nextUntil([селектор|элемент]) — Данный метод выполняет следующее: он для каждого элемента текущего набора осуществляет поиск всех следующих за ним элементов (являющиеся по отношению к нему сиблингом) до указанного. Метод .nextUntil() в качестве своего результата — возвращает объект jQuery, состоящий из найденных элементов.

.prev() — Данный метод выполняет следующее: он для каждого элемента текущего набора осуществляет поиск предыдущего элемента, который является по отношению к нему сиблингом (siblings). Метод .prev() в качестве своего результата — возвращает объект jQuery, состоящий из найденных элементов.

.prevAll() — Данный метод выполняет следующее: он для каждого элемента текущего набора осуществляет поиск всех предыдущих элементов, которые являются по отношению к нему сиблингом (siblings). Метод .prevAll() в качестве своего результата — возвращает объект jQuery, состоящий из найденных элементов.

.prevUntil(селектор|элемент) — Данный метод выполняет следующее: он для каждого элемента текущего набора осуществляет поиск всех предыдущих элементов (являющие по отношение к нему сиблингом) до указанного. Метод .prevUntil() в качестве своего результата — возвращает объект jQuery, состоящий из найденных элементов.

.sibling() — Данный метод выполняет следующее: он для каждого элемента текущего набора осуществляет поиск всех элементов в DOM-дереве, которые приходятся ему сиблингами (siblings). Метод .sibling() в качестве своего результата — возвращает объект jQuery, состоящий из найденных элементов.

.children() — Данный метод выполняет следующее: для каждого элемента текущего набора находит все элементы в DOM-дереве, которые приходятся ему детьми (child). Метод .children() в качестве своего результата — возвращает объект jQuery, состоящий из найденных элементов.

.closest(выражение) — Данный метод выполняет следующее: он для каждого элемента текущего набора осуществляет поиск элемента в DOM-дереве, который отвечает указанному в качестве параметра выражению. Поиск элементов данный метод осуществляет начиная с исходного элемента, далее переходит к родителю, потом к родителю родителя и т.д. вверх по DOM-дереву. Метод .closest() в качестве своего результата — возвращает объект jQuery, состоящий из найденных элементов.

.find() — Данный метод выполняет следующее: он для каждого элемента текущего набора осуществляет поиск всех элементов в DOM-дереве, которые приходятся ему потомками (включая детей). Метод .find() в качестве своего результата — возвращает объект jQuery, состоящий из найденных элементов.

.offsetParent() — Данный метод выполняет следующее: он для каждого элемента текущего набора осуществляет поиск его ближайшего элемента-предка, который не расположен в нормальном потоке (т.е. имеет CSS свойство position со значением relative , absolute или fixed ). Метод .offsetParent() в качестве своего результата — возвращает объект jQuery, состоящий из найденных элементов.

.parent() — Данный метод выполняет следующее: он для каждого элемента текущего набора осуществляет поиск его родительского элемента в DOM-дереве. Метод .parent() в качестве своего результата — возвращает объект jQuery, состоящий из найденных элементов.

.parents() — Данный метод выполняет следующее: он для каждого элемента текущего набора осуществляет поиск всех элементов в DOM-дереве, которые приходятся ему предками (включая родителя). Метод .parents() в качестве своего результата — возвращает объект jQuery, состоящий из найденных элементов.

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

Методы, выполняющие различные действия, которые связаны с набором элементов

Кроме этого библиотека jQuery содержит дополнительные методы, которые собраны в категории «Разные» и предназначенные для выполнения различных действий, которые можно отнести к операциям, связанными с наборами элементов.

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

.addBack() — добавить из стека цепочки методов jQuery предыдущий набор элементов в текущий набор. Данный параметр предоставляет возможность отфильтровать элементы предыдущего набора, перед тем как их добавить к текущему набору.

.contents() — осуществляет поиск детей (DOM-узлов) для каждого элемента текущего набора, включая текстовые узлы и узлы комментариев. Данный метод в качестве своего результата возвращает объект jQuery, состоящий из найденных элементов.

.end() — позволяет вернуться к набору элементов, которые были у предыдущей операции фильтрации в пределах текущей цепочки методов jQuery.

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

Что использовать: методы jQuery или нативные методы JavaScript?

Возьмём для примера следующий сниппет:

В данном случае, есть ли какие-то выгоды от использования этого:

в сравнении с этим:

И что из этих двух вариантов является лучшей практикой?

2 ответа 2

Синтетические тесты такие синтетические.

Если посмотреть, что именно происходит в методе text

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

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

Таким образом, если в момент написания скрипта есть точная уверенность из какого типа элементов нужно будет брать текст — можно воспользоваться необходимым свойством напрямую, для кода из вопроса — использовать textContent на непосредственно html элементе. Это позволит избежать расходов на вызов конструктора jQuery и соответствующие проверки внутри самой функции.

Если же неизвестно для чего будет применяться метод — то лучше воспользоваться методом jQuery.

17 нововведений jQuery 3 и советы по их использованию

Прошло уже более 10 лет с того момента, как библиотека jQuery начала своё широкое распространение по Интернету, и она до сих пор пользуется большой популярностью. В июле 2015 года jQuery анонсировала альфа-версию 3.0 — крупнейшее обновление за долгие годы.

Текущая версия 3.1.1, вышедшая в сентябре 2020 года, исправила множество багов, добавила новые методы и удалила избыточные, также изменив поведение некоторых функций. Давайте разберемся в нововведениях, которые были представлены в этой версии.

Методы скрытия и отображения

Для лучшей совместимости с адаптивным дизайном jQuery3 была усовершенствована, получив возможность скрытия нескольких элементов. Тесты показали, что новая версия справляется с этим на 2% быстрее, чем предыдущая.

Кроме того, методы .hide() , .show() и .toggle() будут ориентироваться на inline-стили. Эта особенность позволит корректно работать с функцией display , что позволит правилам CSS изменяться динамически в зависимости от таких событий, как изменение разрешения окна и ориентации экрана.

Методы wrapAll() и unwrap()

В jQuery 2 метод .wrapAll() при передаче функции в качестве аргумента вёл себя точно так же, как и метод .wrap() . Это изменили — теперь .wrapAll(function) вызывает функцию и использует строковое представление результата как обёртку коллекции.

В jQuery 3 также появился опциональный параметр-селектор метода unwrap() . Это нововведение позволяет передавать методу строковое значение, которое содержит выражение селектора.

Полосы прокрутки высоты и ширины теперь учитываются

В jQuery 2 вызов $(window).width() возвращал ширину содержимого, не учитывая полосы прокрутки, добавленные браузером, когда содержимое превышало размеры элемента. Для того, чтобы предоставить возможность измерения, эквивалентную CSS-медиазапросу, $(window).outerWidth() и $(window).outerHeight() теперь возвращают ширину и длину с учётом полос прокрутки. Это эквивалентно свойству DOM window.innerWidth .

Поведение data()

В jQuery 3 поведение метода data() было немного изменено, чтобы он подходил под спецификации Dataset API. Теперь он переводит имена свойств в верблюжью нотацию.

При использовании старой версии вы получите следующий результат:

В jQuery 3 вы получите:

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

Поддержка SVG при операциях с классами

jQuery до сих пор не полностью поддерживает SVG, но методы наподобие .hasClass() или .addClass() , которые управляют CSS-классами, могут быть использованы для работы с SVG. Вы можете изменять или находить классы в SVG, затем применять стили к классам, используя CSS.

Фильтры скрытия и отображения

jQuery 3 изменяет смысл фильтров :visible и :hidden . Он воспринимает элементы как :visible , если у них есть хоть какие-то окна макета, включая те, которые имеют нулевую ширину и длину. Для примера, элемент br и строковые элементы без содержимого будут выделены фильтром :visible .

Если вы имеете следующую HTML-страницу:

и запускаете выражение:

то в jQuery 2, вы получите результат 0 , а в третьей версии результат будет равен 3 .

jQuery больше не округляет параметры высоты и ширины

Теперь jQuery возвращает дробные значения .width() и .height() вместо целого числа, если браузер поддерживает это. Для пользователей, которым нужна субпиксельная точность (например, при дизайне веб-сайтов), это может быть полезным.

Например, у вас есть 3 элемента с шириной, равной одной третьей (33.333333%), внутри контейнера шириной 100px:

Если вы запросите ширину дочернего элемента:

то получите значение 33.33333 , что будет являться более точным результатом.

Дополнительный уровень защиты

Дополнительный уровень был добавлен для защиты от межсайтового скриптинга (XSS). Разработчикам теперь нужно уточнять dataType:”script” в опциях методов $.ajax() и $.get() . Это предотвращает возможность атак. Предоставляем пример кода:

Неприменимый хеш

jQuery 3 возвращает синтаксическую ошибку, если строка селектора состоит лишь из хеша, вроде jQuery(«#») или .find(«#») . В старой версии $(«#») возвращал пустое множество, а .find(«#») — ошибку.

Новый метод для выделения строк

Новый метод jQuery.escapeSelector() позволяет вам выделить любую строку или символ, которые имеют определенное значение в CSS-селекторах.

«Бастион», Москва, от 80 000 до 200 000 ₽

Например, если элемент на странице имеет id “abc.xyz”, то он не может быть выбран методом $(«abc.xyz») , т.к. селектор будет распознан как элемент с id “abc”, и классом “xyz”. Однако он может быть выбран новой функцией $(«#» + $.escapeSelector(«abc.xyz»)) .

Аргументы jQuery.when()

В jQuery 3 при добавлении методом then() аргумента к $.when() , он возвращает его promise-версию. Это расширяет возможности для ввода, включая промисы Bluebird и промисы ES6, что дает возможность писать более сложные асинхронные обратные вызовы.

Хеш в URL

Теперь функция jQuery.ajax() больше не удаляет хеш в URL, если он присутствует. Однако, вам придется удалять его вручную до отправки запроса, если сервер на другом конце соединения не может обработать URL с хешем.

Deferred-объекты совместимы с JS-промисами

Deferred’ы — это объекты которые можно соединять цепными обратными вызовами. jQuery 3 сделал их совместимыми с новыми стандартами Promises/A+. Также есть ключевое изменение в функции .then() . Любое исключение, выбрасываемое в рамках обратного вызова .then() , теперь конвертируется в отклоняемое значение. Непромисообразные значения, возвращенные обработчиком отклонений, меняются на выполняемые значения.

Новый стандарт поведения Promises/A+:

Новый API для анимации

jQuery 3 использует API requestAnimationFrame() для работы с анимацией. Этот API воспроизводит анимации плавнее и быстрее, затрачивая меньше вычислительного времени. Он используется лишь в тех браузерах, которые поддерживают этот API. Для старых же браузеров, таких как Internet Explorer 9, jQuery использует старый API в качестве запасного варианта.

jQuery 3 работает в строгом режиме

Большинство браузеров, поддерживающих jQuery3, используют строгий режим (strict mode). Новая версия была создана с учётом это. Несмотря на то, что jQuery 3 была написана в строгом режиме, вашему коду не обязательно использовать его. Следовательно, вам не нужно переписывать уже существующий код, если вы желаете перейти на новую версию. Однако есть одно исключение: некоторые версии ASP.NET не совместимы из-за строгого режима.

Новая сигнатура методов get и post

jQuery получила новые сигнатуры сервисных функций $.get() и $.post() для единообразия с $.ajax() .

Оператор цикла for…of

jQuery 3 поддерживает оператор цикла for..of , который имеется в спецификации ECMAScript 6. Это позволяет вам запускать цикл по итерируемым объектам, таким как Map , Set , Array и т.д.

Оператор цикла for..of может быть использован для замены синтаксической конструкции $.each( ) . Предположим, что вы хотите применить имя к каждому вводимому элементу страницы.

Код на jQuery 2 выглядит так:

Но код на jQuery 3 будет иметь следующий вид:

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

Массивы предоставляют множество методов. Чтобы было проще, в этой главе они разбиты на группы.

Добавление/удаление элементов

Мы уже знаем методы, которые добавляют и удаляют элементы из начала или конца:

  • arr.push(. items) – добавляет элементы в конец,
  • arr.pop() – извлекает элемент из конца,
  • arr.shift() – извлекает элемент из начала,
  • arr.unshift(. items) – добавляет элементы в начало.

splice

Как удалить элемент из массива?

Так как массивы – это объекты, то можно попробовать delete :

Вроде бы, элемент и был удалён, но при проверке оказывается, что массив всё ещё имеет 3 элемента arr.length == 3 .

Это нормально, потому что всё, что делает delete obj.key – это удаляет значение с данным ключом key . Это нормально для объектов, но для массивов мы обычно хотим, чтобы оставшиеся элементы сдвинулись и заняли освободившееся место. Мы ждём, что массив станет короче.

Поэтому для этого нужно использовать специальные методы.

Метод arr.splice(str) – это универсальный «швейцарский нож» для работы с массивами. Умеет всё: добавлять, удалять и заменять элементы.

Он начинает с позиции index , удаляет deleteCount элементов и вставляет elem1, . elemN на их место. Возвращает массив из удалённых элементов.

Этот метод проще всего понять, рассмотрев примеры.

Начнём с удаления:

Легко, правда? Начиная с позиции 1 , он убрал 1 элемент.


В следующем примере мы удалим 3 элемента и заменим их двумя другими.

Здесь видно, что splice возвращает массив из удалённых элементов:

Метод splice также может вставлять элементы без удаления, для этого достаточно установить deleteCount в 0 :

В этом и в других методах массива допускается использование отрицательного индекса. Он позволяет начать отсчёт элементов с конца, как тут:

slice

Метод arr.slice намного проще, чем похожий на него arr.splice .

Он возвращает новый массив, в который копирует элементы, начиная с индекса start и до end (не включая end ). Оба индекса start и end могут быть отрицательными. В таком случае отсчёт будет осуществляться с конца массива.

Это похоже на строковый метод str.slice , но вместо подстрок возвращает подмассивы.

Можно вызвать slice и вообще без аргументов: arr.slice() создаёт копию массива arr . Это часто используют, чтобы создать копию массива для дальнейших преобразований, которые не должны менять исходный массив.

concat

Метод arr.concat создаёт новый массив, в который копирует данные из других массивов и дополнительные значения.

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

В результате мы получаем новый массив, включающий в себя элементы из arr , а также arg1 , arg2 и так далее…

Если аргумент argN – массив, то все его элементы копируются. Иначе скопируется сам аргумент.

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

…Но если объект имеет специальное свойство Symbol.isConcatSpreadable , то он обрабатывается concat как массив: вместо него добавляются его числовые свойства.

Для корректной обработки в объекте должны быть числовые свойства и length :

Перебор: forEach

Метод arr.forEach позволяет запускать функцию для каждого элемента массива.

Например, этот код выведет на экран каждый элемент массива:

А этот вдобавок расскажет и о своей позиции в массиве:

Результат функции (если она вообще что-то возвращает) отбрасывается и игнорируется.

Поиск в массиве

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

indexOf/lastIndexOf и includes

Методы arr.indexOf, arr.lastIndexOf и arr.includes имеют одинаковый синтаксис и делают по сути то же самое, что и их строковые аналоги, но работают с элементами вместо символов:

  • arr.indexOf(item, from) ищет item , начиная с индекса from , и возвращает индекс, на котором был найден искомый элемент, в противном случае -1 .
  • arr.lastIndexOf(item, from) – то же самое, но ищет справа налево.
  • arr.includes(item, from) – ищет item , начиная с индекса from , и возвращает true , если поиск успешен.

Обратите внимание, что методы используют строгое сравнение === . Таким образом, если мы ищем false , он находит именно false , а не ноль.

Если мы хотим проверить наличие элемента, и нет необходимости знать его точный индекс, тогда предпочтительным является arr.includes .

Кроме того, очень незначительным отличием includes является то, что он правильно обрабатывает NaN в отличие от indexOf/lastIndexOf :

find и findIndex

Представьте, что у нас есть массив объектов. Как нам найти объект с определённым условием?

Здесь пригодится метод arr.find.

Его синтаксис таков:

Функция вызывается по очереди для каждого элемента массива:

  • item – очередной элемент.
  • index – его индекс.
  • array – сам массив.

Если функция возвращает true , поиск прерывается и возвращается item . Если ничего не найдено, возвращается undefined .

Например, у нас есть массив пользователей, каждый из которых имеет поля id и name . Попробуем найти того, кто с >:

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

Обратите внимание, что в данном примере мы передаём find функцию item => item. >, с одним аргументом. Это типично, дополнительные аргументы этой функции используются редко.

Метод arr.findIndex – по сути, то же самое, но возвращает индекс, на котором был найден элемент, а не сам элемент, и -1 , если ничего не найдено.

filter

Метод find ищет один (первый попавшийся) элемент, на котором функция-колбэк вернёт true .

На тот случай, если найденных элементов может быть много, предусмотрен метод arr.filter(fn).

Синтаксис этого метода схож с find , но filter возвращает массив из всех подходящих элементов:

Преобразование массива

Перейдём к методам преобразования и упорядочения массива.

Метод arr.map является одним из наиболее полезных и часто используемых.

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

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

sort(fn)

Вызов arr.sort() сортирует массив на месте, меняя в нём порядок элементов.

Он возвращает отсортированный массив, но обычно возвращаемое значение игнорируется, так как изменяется сам arr .

Не заметили ничего странного в этом примере?

Порядок стал 1, 15, 2 . Это неправильно! Но почему?

По умолчанию элементы сортируются как строки.

Буквально, элементы преобразуются в строки при сравнении. Для строк применяется лексикографический порядок, и действительно выходит, что «2» > «15» .

Чтобы использовать наш собственный порядок сортировки, нам нужно предоставить функцию в качестве аргумента arr.sort() .

Функция должна для пары значений возвращать:

Например, для сортировки чисел:

Теперь всё работает как надо.

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

Метод arr.sort(fn) реализует общий алгоритм сортировки. Нам не нужно заботиться о том, как он работает внутри (в большинстве случаев это оптимизированная быстрая сортировка). Она проходится по массиву, сравнивает его элементы с помощью предоставленной функции и переупорядочивает их. Всё, что остаётся нам, это предоставить fn , которая делает это сравнение.

Кстати, если мы когда-нибудь захотим узнать, какие элементы сравниваются – ничто не мешает нам вывести их на экран:

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

На самом деле от функции сравнения требуется любое положительное число, чтобы сказать «больше», и отрицательное число, чтобы сказать «меньше».

Это позволяет писать более короткие функции:

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

Будет работать точно так же, как и более длинная версия выше.

reverse

Метод arr.reverse меняет порядок элементов в arr на обратный.

Он также возвращает массив arr с изменённым порядком элементов.

split и join

Ситуация из реальной жизни. Мы пишем приложение для обмена сообщениями, и посетитель вводит имена тех, кому его отправить, через запятую: Вася, Петя, Маша . Но нам-то гораздо удобнее работать с массивом имён, чем с одной строкой. Как его получить?

Метод str.split(delim) именно это и делает. Он разбивает строку на массив по заданному разделителю delim .

В примере ниже таким разделителем является строка из запятой и пробела.

У метода split есть необязательный второй числовой аргумент – ограничение на количество элементов в массиве. Если их больше, чем указано, то остаток массива будет отброшен. На практике это редко используется:

Вызов split(s) с пустым аргументом s разбил бы строку на массив букв:

Вызов arr.join(glue) делает в точности противоположное split . Он создаёт строку из элементов arr , вставляя glue между ними.

reduce/reduceRight

Если нам нужно перебрать массив – мы можем использовать forEach , for или for..of .

Если нам нужно перебрать массив и вернуть данные для каждого элемента – мы используем map .

Методы arr.reduce и arr.reduceRight похожи на методы выше, но они немного сложнее. Они используются для вычисления какого-нибудь единого значения на основе всего массива.

Функция применяется по очереди ко всем элементам массива и «переносит» свой результат на следующий вызов.

  • previousValue – результат предыдущего вызова этой функции, равен initial при первом вызове (если передан initial ),
  • item – очередной элемент массива,
  • index – его индекс,
  • array – сам массив.

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

Звучит сложновато, но всё становится проще, если думать о первом аргументе как «аккумулирующем» результат предыдущих вызовов функции. По окончании он становится результатом reduce .

Этот метод проще всего понять на примере.

Тут мы получим сумму всех элементов массива всего одной строкой:

Здесь мы использовали наиболее распространённый вариант reduce , который использует только 2 аргумента.

Давайте детальнее разберём, как он работает.

  1. При первом запуске sum равен initial (последний аргумент reduce ), то есть 0 , а current – первый элемент массива, равный 1 . Таким образом, результат функции равен 1 .
  2. При втором запуске sum = 1 , и к нему мы добавляем второй элемент массива ( 2 ).
  3. При третьем запуске sum = 3 , к которому мы добавляем следующий элемент, и так далее…

Поток вычислений получается такой:

В виде таблицы, где каждая строка –- вызов функции на очередном элементе массива:

sum current result
первый вызов 1 1
второй вызов 1 2 3
третий вызов 3 3 6
четвёртый вызов 6 4 10
пятый вызов 10 5 15

Здесь отчётливо видно, как результат предыдущего вызова передаётся в первый аргумент следующего.

Мы также можем опустить начальное значение:

Результат – точно такой же! Это потому, что при отсутствии initial в качестве первого значения берётся первый элемент массива, а перебор стартует со второго.

Таблица вычислений будет такая же за вычетом первой строки.

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

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

Метод arr.reduceRight работает аналогично, но проходит по массиву справа налево.

Array.isArray

Массивы не образуют отдельный тип языка. Они основаны на объектах.

Поэтому typeof не может отличить простой объект от массива:

…Но массивы используются настолько часто, что для этого придумали специальный метод: Array.isArray(value). Он возвращает true , если value массив, и false , если нет.

Большинство методов поддерживают «thisArg»

Почти все методы массива, которые вызывают функции – такие как find , filter , map , за исключением метода sort , принимают необязательный параметр thisArg .

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

Вот полный синтаксис этих методов:

Значение параметра thisArg становится this для func .

Например, вот тут мы используем метод объекта army как фильтр, и thisArg передаёт ему контекст:

Если бы мы в примере выше использовали просто users.filter(army.canJoin) , то вызов army.canJoin был бы в режиме отдельной функции, с this=undefined . Это тут же привело бы к ошибке.

Вызов users.filter(army.canJoin, army) можно заменить на users.filter(user => army.canJoin(user)) , который делает то же самое. Последняя запись используется даже чаще, так как функция-стрелка более наглядна.

Итого

Шпаргалка по методам массива:

Для добавления/удаления элементов:

  • push (. items) – добавляет элементы в конец,
  • pop() – извлекает элемент с конца,
  • shift() – извлекает элемент с начала,
  • unshift(. items) – добавляет элементы в начало.
  • splice(pos, deleteCount, . items) – начиная с индекса pos , удаляет deleteCount элементов и вставляет items .
  • slice(start, end) – создаёт новый массив, копируя в него элементы с позиции start до end (не включая end ).
  • concat(. items) – возвращает новый массив: копирует все члены текущего массива и добавляет к нему items . Если какой-то из items является массивом, тогда берутся его элементы.

Для поиска среди элементов:

  • indexOf/lastIndexOf(item, pos) – ищет item , начиная с позиции pos , и возвращает его индекс или -1 , если ничего не найдено.
  • includes(value) – возвращает true , если в массиве имеется элемент value , в противном случае false .
  • find/filter(func) – фильтрует элементы через функцию и отдаёт первое/все значения, при прохождении которых через функцию возвращается true .
  • findIndex похож на find , но возвращает индекс вместо значения.

Для перебора элементов:

  • forEach(func) – вызывает func для каждого элемента. Ничего не возвращает.

Для преобразования массива:

  • map(func) – создаёт новый массив из результатов вызова func для каждого элемента.
  • sort(func) – сортирует массив «на месте», а потом возвращает его.
  • reverse() – «на месте» меняет порядок следования элементов на противоположный и возвращает изменённый массив.
  • split/join – преобразует строку в массив и обратно.
  • reduce(func, initial) – вычисляет одно значение на основе всего массива, вызывая func для каждого элемента и передавая промежуточный результат между вызовами.
  • Array.isArray(arr) проверяет, является ли arr массивом.

Обратите внимание, что методы sort , reverse и splice изменяют исходный массив.

Изученных нами методов достаточно в 99% случаев, но существуют и другие.

Функция fn вызывается для каждого элемента массива аналогично map . Если какие-либо/все результаты вызовов являются true , то метод возвращает true , иначе false .

arr.fill(value, start, end) – заполняет массив повторяющимися value , начиная с индекса start до end .

arr.copyWithin(target, start, end) – копирует свои элементы, начиная со start и заканчивая end , в собственную позицию target (перезаписывает существующие).

Полный список есть в справочнике MDN.

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

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

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

Задачи

Переведите текст вида border-left-width в borderLeftWidth

Напишите функцию camelize(str) , которая преобразует строки вида «my-short-string» в «myShortString».

То есть дефисы удаляются, а все слова после них получают заглавную букву.

Мастер Йода рекомендует:  Курс «Проектирование информационных систем»
Добавить комментарий