DOM непрерывно развивается. Какие-то браузеры его адаптируют быстрее, какие-то медленнее. Все это не позволяет легко и непринужденно пользоваться последними новинками. Разработчикам каждый раз нужно думать, какие браузеры распространены у пользователей их проектов.
Как выяснить, какие браузеры актуальны? Обычно об этом узнают из аналитики. Например, можно использовать Google Analytics, которая в режиме реального времени собирает данные обо всех, кто заходит на сайт.
В особо сложных ситуациях приходится поддерживать совсем старые браузеры, которые практически ничего не могут. Такое нередко встречается в государственных организациях.
Например, есть метод matches()
, который ищет элементы по CSS-селекторам. Он поддерживается Internet Explorer, но только с девятой версии. Если в вашем проекте заявлена совместимость с восьмой версией, то на вызов этого метода мы получим ошибку:
const div = document.querySelector('div');
div.matches('.someClass'); // Uncaught TypeError: matches is not a function
К счастью, JavaScript позволяет частично компенсировать недостатки старых браузеров. Благодаря прототипам разработчики могут добавить недостающую функциональность прямо в реализацию DOM. Делается это с помощью полифилов, которые мы изучим сегодня.
Общий принцип работы этих библиотек следующий:
- Проверяем наличие нужного метода или свойства
- Если их нет, то добавляем
Важно, чтобы библиотека с полифилами грузилась до выполнения любого другого кода. Только в этом случае остальной код может рассчитывать на то, что все нужные свойства будут в наличии.
Добавление метода
Рассмотрим пример полифила для метода node.matches()
. Он работает для всех популярных браузеров и задействует их специфику, что видно по именам свойств:
(function(constructor) {
const p = constructor.prototype;
if (!p.matches) {
p.matches = p.matchesSelector ||
p.mozMatchesSelector ||
p.msMatchesSelector ||
p.oMatchesSelector ||
p.webkitMatchesSelector;
};
})(window.Element);
После выполнения этого кода мы можем использовать метод element.matches()
, не боясь, что его не будет в старых браузерах.
Добавление свойства
Более сложный вариант – добавление свойства ParentNode.lastElementChild
. Здесь приходится программировать логику поиска нужного элемента:
// Обратите внимание, что добавление свойства производится особым образом,
// из-за которого свойство становится динамическим и ленивым
// Другими словами, его значение будет вычисляться только в момент обращения
if (!('lastElementChild' in document.documentElement)) {
Object.defineProperty(Element.prototype, 'lastElementChild', {
get: function() {
for (let nodes = this.children, n, i = nodes.length — 1; i >= 0; --i) {
if (n = nodes[i], 1 === n.nodeType) {
return n;
}
}
return null;
}
});
}
Примеры выше не совсем полные. Если бы мы посмотрели исходники соответствующих библиотек, мы бы удивились, как много кода в них. Все таки обеспечение универсальной работы во всех браузерах и всех версиях — это непростая задача.
Чтобы проверить поддержку определенных фич в разных браузерах, можно воспользоваться ресурсом Can I use:
А самый простой способ добавить полифиллы на сайт — это воспользоваться проектом polyfill-fastly.io.
Кроме этого проекта, на GitHub есть много готовых полифилов для любых частей DOM. Они разбросаны по разным репозиториям разных людей. Поэтому если вам понадобится что-то полифилить, то сначала придется поискать нужную библиотеку.
Иногда нам нужно просто проверить наличие определенной фичи и выполнить разный код в зависимости от результата. В такой ситуации поможет библиотека modernizr:
// Проверяется наличие flash
Modernizr.on('flash', (result) => {
if (result) {
// the browser has flash
} else {
// the browser does not have flash
}
});
Ядро JavaScript
Полифиллы бывают не только для DOM. Сам JavaScript тоже непрерывно развивается.
Многие фичи современного JavaScript настолько упростили разработку, что без них уже сложно. Поэтому практически ни один современный проект не обходится без библиотеки core-js. Она закрывает почти все возможности современного JavaScript.
Чтобы использовать эту библиотеку, нужно установить ее как зависимость проекта и подключить ее на самом верхнем уровне приложения. И все — дальше она делает всю работу сама, поэтому нам не приходится собирать приложения через webpack:
import 'core-js/stable';
// Другие зависимости
Далее в курсе будут упражнения, где в index.js вы увидите подключение этой библиотеки.
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.