Полифил
Полифил — это фрагмент кода (в сети — обычно JavaScript), который позволяет использовать современную функциональность в более старых браузерах, которые не поддерживают ее по умолчанию.
Например, полифил можно использовать, чтобы эмулировать функциональность text-shadow в IE7 с помощью нативных фильтров браузера, или рем и медиавыражения, динамически меняя стилизацию в нужных случаях с помощью JavaScript, или что-либо еще, что вам потребуется.
Из-за меньшей производительности и ограниченной функциональности нельзя использовать исключительно полифилы. Нативная реализация API быстрее и с ней можно сделать больше, чем с помощью полифила. Например, полифил Object.create может эмулировать только то, что доступно для ненативной реализации Object.create.
В других случаях полифилы нужны, чтобы разрешить ситуации, когда браузеры реализуют одни и те же возможности разными способами. Тогда полифил использует нестандартные возможности конкретного браузера, чтобы в результате определенная функциональность была совместима с действующими стандартами JavaScript. Хотя такое применение полифилов и редкость сейчас, во времена IE6 и Netscape, когда каждый браузер реализовывал JavaScript очень по-разному, оно было широко распространено. Первая версия JQuery была ранним примером полифила. Она представляла собой компиляцию из обходных путей, специфических для определенных браузеров, которая предоставляла JavaScript-разработчикам единый API для всех браузеров. В то время одной из наибольших проблем было заставить сайт работать на всех устройствах: браузеры настолько существенно различались, что порой код приходилось писать совершенно по-разному и разрабатывать разные пользовательские интерфейсы, исходя из используемого пользователем браузера. Таким образом, у JavaScript-разработчиков был доступ только к очень лимитированному количеству JavaScript API, которые работали более или менее одинаково во всех браузерах. Сейчас использование полифилов для взаимодействия со специфичными для браузера реализациями возможностей менее распространено, так как современные браузеры в большинстве своем имеют большой набор стандартизированных API.
Узнать больше
Общая информация
- Что такое полифил? (перевод статьи Реми Шарпа, создателя термина «полифил»)
Found a content problem with this page?
- Edit the page on GitHub.
- Report the content issue.
- View the source on GitHub.
This page was last modified on 3 авг. 2023 г. by MDN contributors.
Полифилы JavaScript: что это и зачем они нужны?
Всем привет, я — Кирилл Мыльников, frontend разработчик компании Usetech.
Сегодня хочу рассказать о полифилах JavaScript: что это и зачем они нужны? На практике мы реализуем несколько полифилов: map, forEach, filter, reduce.
Эта статья подойдёт новичкам, которые готовятся к собеседованию, и опытным специалистам. В комментариях вы можете рассказать о том, как реализуете полифилы в своей работе.
Итак, начнём с определения полифила, а затем перейдём к методам.
Что такое полифил?
Полифил — это код, реализующий какую-то функциональность, которая не поддерживается в некоторых браузерах. Реализация собственного полифила обеспечивает единообразное поведение функциональности в разных браузерах.
Как я писал выше, сегодня мы будем реализовывать несколько полифилов: map, forEach, filter, reduce.
Метод map
Метод map вызывает функцию для каждого элемента и возвращает новый массив. Аргумент функции принимает три значения:
- Элемент массива;
- Индекс данного элемента;
- Сам массив.
Реализуем полифил на примере:
Array.prototype.myMap = function (callback, arg) < if (this == null || this === window) < throw TypeError('myMap called on null or undefined') >if (typeof callback !== 'function') < throw TypeError(`is not a function`) > const newArray = []; for (let i = 0; i < this.length; i++) < newArray[i] = callback.call(arg, this[i], i, this) >return newArray; >
А теперь поэтапно разберём, что тут происходит. Сначала нам нужно обработать возникающие ошибки:
- Функцию обратного вызова могут не передать;
- Данный метод вызывается не для массива.
this === null || this === window , условие сработает в том случае, если метод вызывается как отдельная функция.
Пример:
const myMap = Array.prototype.myMap;
Внутри функции myMap this уже будет как global, не в строгом режиме будет window, в строгом undefined. Для этого кейса мы выкидываем ошибку.
Также функцию обратного вызова могут не передать, и на этот случай мы делаем проверку на typeof callback === ‘function’
Наша функция принимает второй аргумент arg. Для чего это нужно? Если наша функция обратного вызова должна быть вызвана в контексте, для внутреннего callback должно быть установлено значение arg. Это можно сделать с помощью call() .
Вот таким простым способом мы с вами реализовали полифил метода map. Теперь перейдём к следующему методу.
Метод forEach
При реализации следующего полифила метода forEach нужно учесть несколько моментов:
- Он используется только для перебора и ничего не возвращает;
- Изменяет оригинальный массив.
Реализация полифила будет очень похожа на метод map. Посмотрим на примере:
Array.prototype.myForEach = function (callback, arg) < if (this == null || this === window) throw TypeError('myForEach called on null or undefined'); if (typeof callback !== 'function') throw TypeError(`$is not a function`); for (let i = 0; i < this.length; i++) < callback.call(arg, this[i], i, this); >>;
Проверки остались такими же, как и реализация, только мы ничего не возвращаем, а просто перебираем.
Метод filter
Этот метод возвращает новый массив всех подходящих элементов. Посмотрим пример:
Array.prototype.myfilter = function (callback, arg) < if (this == null || this === window) throw TypeError('myfilter called on null or undefined'); if (typeof callback !== 'function') throw TypeError(`$is not a function`); const newArr = []; for (let i = 0; i < this.length; i++) < if (callback.call(arg, this[i], i, this)) newArr.push(this[i]); >return newArr; >;
Как вы видите, в этом случае присутствует обработка ошибок, как и у всех.
Единственное, что поменялось, это то, что мы написали проверку, удовлетворяющую условию, перед тем как добавить в массив и вернуть его.
Перейдём к последнему методу — reduce.
Метод reduce
Прежде чем приступить к разбору на практике, нужно вспомнить, как работает метод reduce. В основном его применяют для вычисления какого-нибудь единого значения на основе всего массива. Функция применяется по очереди ко всем элементам и переносит свой результат на следующий вызов.
- previousValue — результат предыдущего вызова;
- item — элемент массива;
- index — индекс данного элемента;
- array — сам массив.
Теперь перейдём к реализации полифила reduce:
Array.prototype.myReduce = function (callback, initValue) < if (this === null || this === window) throw TypeError('myReduce called on null or undefined'); if (typeof callback !== 'function') throw TypeError(`$is not a function`); let previousValue = initValue; let startIndex = 0; if (initValue === null) < previousValue = this[0]; startIndex = 1; >if (previousValue == null) throw TypeError('Reduce of empty array with no initial value'); for (let index = startIndex; index < this.length; index++) < previousValue = callback(previousValue, this[index], index, this); >return previousValue; >;
Первые две проверки я уже описывал выше. Но появилась новая проверка: если previousValue будет undefined, если массив пуст и не указан initialValue, то тоже выдаём ошибку.
Второй аргумент reduce initialValue необязательный, и он используется для инициализации previousValue. Если он не указан, то мы инициализируем первый элемент массива, и начинаем обход со второго элемента.
Мы разобрали несколько примеров реализации полифилов, а также возникающие ошибки и методы их исправления. Спасибо за то, что уделили время прочтению статьи. А в комментариях можете поделиться своим опытом создания и реализации полифилов.
- Блог компании Usetech
- JavaScript
Полифиллы — JS: DOM API
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.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'; // Другие зависимости
Открыть доступ
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно
- 130 курсов, 2000+ часов теории
- 1000 практических заданий в браузере
- 360 000 студентов
Наши выпускники работают в компаниях:
Полифилы что это такое
Здравствуйте! В этом уроке я вкратце хочу осветить такой вопрос, как полифилы. Надо отметить, что JavaScript – это динамично развивающийся язык программирования. Регулярно появляются предложения о добавлении в него новых возможностей, они естественно анализируются, и, если предложения одобряются, то описания новых возможностей языка переносятся в черновик стандарта, а затем уже публикуются в спецификации.
Разработчики JavaScript-движков сами решают, какие предложения реализовывать. Они могут заранее добавить в браузеры поддержку функций, которые всё ещё находятся в черновом варианте, и отложить разработку функций, которые уже перенесены в спецификацию, потому что они менее интересны разработчикам или более сложные в реализации.
Таким образом, довольно часто реализуется только часть стандарта.
Babel
Когда мы используем современные возможности JavaScript, некоторые движки могут к сожалению не поддерживать их. Как было сказано выше, не везде реализованы все функции.
И тут приходит на помощь Babel.
Babel – это такой транспилер. Он переписывает современный JavaScript-код в предыдущий стандарт.
На самом деле, есть 2 части Babel:
- Во-первых, транспилер, который и переписывает код. Разработчик запускает Babel на своём компьютере. Он переписывает код в более старый стандарт. И после этого код отправляется на сайт. Современные сборщики проектов, такие как webpack, предоставляют возможность запускать транспилер автоматически после каждого изменения кода, что позволяет существенно экономить время.
- Во-вторых, сам полифил.Новые возможности языка могут включать встроенные функции и новые синтаксические конструкции. Транспилер переписывает код, преобразовывая новые синтаксические конструкции в старые. Но что касается новых встроенных функций, нам ведь нужно их как-то реализовать. JavaScript является высоко динамичным языком, скрипты могут добавлять/изменять любые функции, чтобы они вели себя в соответствии с современным стандартом.Термин «полифил» означает, что скрипт «заполняет» пробелы и добавляет новые современные функции. 2 интересных хранилища полифилов:
- core js поддерживает много функций, можно подключать только нужные.
- polyfill.io – сервис, который автоматически создаёт скрипт с полифилом в зависимости от необходимых функций и браузера самого пользователя.
Читайте также Замыкания и самовызывающиеся функции
Таким образом, чтобы современные функции поддерживались в старых движках, вам надо установить транспилер и добавить полифил.
Браузер Google Chrome поддерживает современные функции, можно запускать новейшие примеры без каких-либо транспилеров, но и другие современные браузеры тоже хорошо работают.
Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.