\n```\n\n**Подход 2: Использование polyfill.io**\n\n```html\n\n\n```\n\n**Подход 3: Webpack и babel-polyfill**\n\n```javascript\n// webpack.config.js\nmodule.exports = {\n entry: ['@babel/polyfill', './src/index.js'],\n // ...\n};\n\n// Или в .babelrc\n{\n \"presets\": [\n [\n \"@babel/preset-env\",\n {\n \"useBuiltIns\": \"usage\",\n \"corejs\": 3\n }\n }\n ]\n}\n```\n\n## 6. Реальный пример: поддержка IE11\n\nНа одном проекте нужно было поддерживать IE11. Я создал файл полифилов:\n\n```javascript\n// polyfills.js\n// Полифилл для Array.from\nif (!Array.from) {\n Array.from = (function() {\n const toStr = Object.prototype.toString;\n const isCallable = (fn) => typeof fn === 'function';\n \n return function from(arrayLike, mapFn, thisArg) {\n if (arrayLike == null) {\n throw new TypeError('Array.from requires an array-like object');\n }\n \n const mapFnIsCallable = isCallable(mapFn);\n const T = thisArg;\n const len = Math.floor(Object(arrayLike).length);\n const A = new Array(len);\n let k = 0;\n \n while (k < len) {\n const kValue = Object(arrayLike)[k];\n A[k] = mapFnIsCallable ? mapFn.call(T, kValue, k) : kValue;\n k += 1;\n }\n \n A.length = len;\n return A;\n };\n }());\n}\n\n// Полифилл для String.prototype.startsWith\nif (!String.prototype.startsWith) {\n String.prototype.startsWith = function(search, pos) {\n pos = !pos || pos < 0 ? 0 : +pos;\n return this.substr(pos, search.length) === search;\n };\n}\n\n// Полифилл для Object.entries\nif (!Object.entries) {\n Object.entries = function(obj) {\n const entries = [];\n for (const key in obj) {\n if (obj.hasOwnProperty(key)) {\n entries.push([key, obj[key]]);\n }\n }\n return entries;\n };\n}\n```\n\n## 7. Тестирование полифилов\n\n```javascript\n// test-polyfills.js\ndescribe('Polyfills', () => {\n it('Array.includes should work', () => {\n const arr = [1, 2, 3];\n expect(arr.includes(2)).toBe(true);\n expect(arr.includes(5)).toBe(false);\n });\n \n it('Object.assign should merge objects', () => {\n const target = { a: 1 };\n const source = { b: 2 };\n const result = Object.assign(target, source);\n \n expect(result).toEqual({ a: 1, b: 2 });\n expect(result === target).toBe(true);\n });\n \n it('Promise should resolve correctly', (done) => {\n const promise = new Promise((resolve) => {\n resolve('success');\n });\n \n promise.then((result) => {\n expect(result).toBe('success');\n done();\n });\n });\n});\n```\n\n## Практические рекомендации\n\n1. **Проверьте требования браузеров** - не добавляйте полифилы, если вам не нужно поддерживать старые браузеры\n\n2. **Используйте инструменты** - babel с @babel/preset-env автоматически добавит нужные полифилы\n\n3. **Минимизируйте размер** - полифилы увеличивают размер бандла. Загружайте их условно\n\n4. **Проверяйте производительность** - полифилы могут быть медленнее нативной реализации\n\n5. **Документируйте** - указывайте, какие полифилы используются и почему\n\n6. **Регулярно обновляйте** - со временем старые браузеры отмирают, и полифилы можно удалить\n\n## Моя практика\n\nСейчас в большинстве проектов я:\n- Использую babel с @babel/preset-env и опцией useBuiltIns: 'usage'\n- Отказался от IE11 поддержки несколько лет назад (его доля < 1%)\n- Для мобильных браузеров использую условную загрузку полифилов через feature detection\n- Всегда измеряю размер бандла и убираю ненужные полифилы","dateCreated":"2026-04-03T17:54:07.138991","upvoteCount":0,"author":{"@type":"Person","name":"claude-haiku-4.5"}}}}
← Назад к вопросам

Как применял полифилы на практике?

2.0 Middle🔥 151 комментариев
#Браузер и сетевые технологии#Оптимизация и производительность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Практическое применение полифилов

Полифилы - это код, который обеспечивает функциональность в старых браузерах, которые не поддерживают новые возможности JavaScript. За 10+ лет я регулярно использовал их для поддержки старых версий браузеров.

1. Понимание полифилов

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

// Полифилл для Array.prototype.includes (IE11 не поддерживает)
if (!Array.prototype.includes) {
  Object.defineProperty(Array.prototype, 'includes', {
    value: function(searchElement, fromIndex) {
      if (this == null) {
        throw new TypeError('Array.prototype.includes called on null or undefined');
      }
      
      const O = Object(this);
      const len = parseInt(O.length) || 0;
      
      if (len === 0) return false;
      
      const n = parseInt(fromIndex) || 0;
      let k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
      
      function sameValueZero(x, y) {
        return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));
      }
      
      while (k < len) {
        if (sameValueZero(O[k], searchElement)) {
          return true;
        }
        k++;
      }
      return false;
    }
  });
}

2. Полифилл для Object.assign

Эта функция критична для работы с объектами в старых браузерах:

// Полифилл для Object.assign (IE11)
if (typeof Object.assign !== 'function') {
  Object.defineProperty(Object, 'assign', {
    value: function assign(target, varArgs) {
      'use strict';
      if (target === null || target === undefined) {
        throw new TypeError('Cannot convert undefined or null to object');
      }
      
      const to = Object(target);
      
      for (let index = 1; index < arguments.length; index++) {
        const nextSource = arguments[index];
        
        if (nextSource !== null && nextSource !== undefined) {
          for (const nextKey in nextSource) {
            if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
              to[nextKey] = nextSource[nextKey];
            }
          }
        }
      }
      return to;
    },
    writable: true,
    configurable: true
  });
}

// Использование в коде
const defaults = { timeout: 5000, retries: 3 };
const options = { timeout: 10000 };
const finalOptions = Object.assign({}, defaults, options);
console.log(finalOptions); // { timeout: 10000, retries: 3 }

3. Полифилл для Promise

Один из самых важных полифилов для старых браузеров:

// Упрощенный полифилл для Promise
if (typeof Promise === 'undefined') {
  window.Promise = function(executor) {
    let state = 'pending';
    let value;
    const handlers = [];
    
    const resolve = (val) => {
      if (state !== 'pending') return;
      state = 'fulfilled';
      value = val;
      handlers.forEach(handle);
    };
    
    const reject = (reason) => {
      if (state !== 'pending') return;
      state = 'rejected';
      value = reason;
      handlers.forEach(handle);
    };
    
    const handle = (handler) => {
      if (state === 'pending') {
        handlers.push(handler);
      } else {
        if (state === 'fulfilled' && handler.onFulfilled) {
          handler.onFulfilled(value);
        }
        if (state === 'rejected' && handler.onRejected) {
          handler.onRejected(value);
        }
      }
    };
    
    executor(resolve, reject);
    
    this.then = function(onFulfilled, onRejected) {
      return new Promise((resolve, reject) => {
        handle({
          onFulfilled: (value) => {
            try {
              resolve(onFulfilled(value));
            } catch (error) {
              reject(error);
            }
          },
          onRejected: (reason) => {
            try {
              reject(onRejected(reason));
            } catch (error) {
              reject(error);
            }
          }
        });
      });
    };
  };
}

4. Полифилл для Fetch API

Fetch был добавлен в браузеры позже XMLHttpRequest. Для IE11 нужен полифилл:

// Простой полифилл для fetch
if (!window.fetch) {
  window.fetch = function(url, options) {
    return new Promise((resolve, reject) => {
      const xhr = new XMLHttpRequest();
      const method = (options && options.method) || 'GET';
      
      xhr.open(method, url);
      
      // Установить headers
      if (options && options.headers) {
        Object.keys(options.headers).forEach(key => {
          xhr.setRequestHeader(key, options.headers[key]);
        });
      }
      
      xhr.onload = () => {
        resolve({
          ok: xhr.status >= 200 && xhr.status < 300,
          status: xhr.status,
          statusText: xhr.statusText,
          text: () => Promise.resolve(xhr.responseText),
          json: () => Promise.resolve(JSON.parse(xhr.responseText))
        });
      };
      
      xhr.onerror = () => {
        reject(new TypeError('Network request failed'));
      };
      
      xhr.send((options && options.body) || null);
    });
  };
}

5. Управление полифилами в проекте

На практике я использовал несколько подходов:

Подход 1: Условная загрузка

<!-- В HTML файле -->
<script>
  // Проверяем, что нужно
  if (!Array.prototype.includes) {
    var script = document.createElement('script');
    script.src = '/polyfills/array-includes.js';
    document.head.appendChild(script);
  }
  
  if (!window.fetch) {
    var script = document.createElement('script');
    script.src = '/polyfills/fetch.js';
    document.head.appendChild(script);
  }
</script>

Подход 2: Использование polyfill.io

<!-- Сервис автоматически отправляет нужные полифилы -->
<script src="https://polyfill.io/v3/polyfill.min.js"></script>

Подход 3: Webpack и babel-polyfill

// webpack.config.js
module.exports = {
  entry: ['@babel/polyfill', './src/index.js'],
  // ...
};

// Или в .babelrc
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "usage",
        "corejs": 3
      }
    }
  ]
}

6. Реальный пример: поддержка IE11

На одном проекте нужно было поддерживать IE11. Я создал файл полифилов:

// polyfills.js
// Полифилл для Array.from
if (!Array.from) {
  Array.from = (function() {
    const toStr = Object.prototype.toString;
    const isCallable = (fn) => typeof fn === 'function';
    
    return function from(arrayLike, mapFn, thisArg) {
      if (arrayLike == null) {
        throw new TypeError('Array.from requires an array-like object');
      }
      
      const mapFnIsCallable = isCallable(mapFn);
      const T = thisArg;
      const len = Math.floor(Object(arrayLike).length);
      const A = new Array(len);
      let k = 0;
      
      while (k < len) {
        const kValue = Object(arrayLike)[k];
        A[k] = mapFnIsCallable ? mapFn.call(T, kValue, k) : kValue;
        k += 1;
      }
      
      A.length = len;
      return A;
    };
  }());
}

// Полифилл для String.prototype.startsWith
if (!String.prototype.startsWith) {
  String.prototype.startsWith = function(search, pos) {
    pos = !pos || pos < 0 ? 0 : +pos;
    return this.substr(pos, search.length) === search;
  };
}

// Полифилл для Object.entries
if (!Object.entries) {
  Object.entries = function(obj) {
    const entries = [];
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        entries.push([key, obj[key]]);
      }
    }
    return entries;
  };
}

7. Тестирование полифилов

// test-polyfills.js
describe('Polyfills', () => {
  it('Array.includes should work', () => {
    const arr = [1, 2, 3];
    expect(arr.includes(2)).toBe(true);
    expect(arr.includes(5)).toBe(false);
  });
  
  it('Object.assign should merge objects', () => {
    const target = { a: 1 };
    const source = { b: 2 };
    const result = Object.assign(target, source);
    
    expect(result).toEqual({ a: 1, b: 2 });
    expect(result === target).toBe(true);
  });
  
  it('Promise should resolve correctly', (done) => {
    const promise = new Promise((resolve) => {
      resolve('success');
    });
    
    promise.then((result) => {
      expect(result).toBe('success');
      done();
    });
  });
});

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

  1. Проверьте требования браузеров - не добавляйте полифилы, если вам не нужно поддерживать старые браузеры

  2. Используйте инструменты - babel с @babel/preset-env автоматически добавит нужные полифилы

  3. Минимизируйте размер - полифилы увеличивают размер бандла. Загружайте их условно

  4. Проверяйте производительность - полифилы могут быть медленнее нативной реализации

  5. Документируйте - указывайте, какие полифилы используются и почему

  6. Регулярно обновляйте - со временем старые браузеры отмирают, и полифилы можно удалить

Моя практика

Сейчас в большинстве проектов я:

  • Использую babel с @babel/preset-env и опцией useBuiltIns: 'usage'
  • Отказался от IE11 поддержки несколько лет назад (его доля < 1%)
  • Для мобильных браузеров использую условную загрузку полифилов через feature detection
  • Всегда измеряю размер бандла и убираю ненужные полифилы