Что такое полифилл?

MDN определяет его как «Полифилл - это фрагмент кода (обычно JavaScript в Интернете), используемый для обеспечения современных функций в старых браузерах, которые изначально не поддерживают его».

Проще говоря, это способ добавить обратную совместимость.

О чем следует помнить при написании полифилла:

1. Какой полифилл мы пишем? Это метод или класс и т. Д.
2. Каковы ожидаемые аргументы моего полифилла и их порядок?
3. Каков тип возвращаемого значения моего полифилла?

Давайте посмотрим на полифил Bind.

В) Какие полифилы мы пишем?
А) Метод

В) Каковы ожидаемые аргументы моего полифилла и их порядок?
А) Первым аргументом должен быть контекст, за которым следует любой аргумент, переданный пользователем

В) Каков тип возвращаемого значения моего полифилла?
А) Bind возвращает новый метод с определенным контекстом

Поскольку привязка вызывается с обозначением точки (.) Для объекта функции, мы определим наш полифилл в прототипе функции.

Привязать полифил с использованием метода «Применить»

Function.prototype.newBindWithApply = function (ctx, ...args) {
 
 // Preserving the current function
 let fn = this;
 // Preserving the default arguments passed with context
 let allArguments = args;
 // returning the new method with context
 return function (args1) {
  allArguments = [...allArguments, ...args1]
  return fn.apply(ctx, allArguments)
 }
}

Привязать полифил без использования метода «Применить»

Function.prototype.newBindWithoutApply = function (ctx, ...args) {
 // Preserving the default arguments passed with context 
 let allArguments = args;
 
 /* Since we are not using call/apply, I'll create a reference of
 binding method within the context, and method will be invoked
 as context.methodcall() */
 
 ctx.fnToCall = this;
 // returning the new method with context
 return function (...args1) {
  allArguments = [...allArguments, ...args1]
  return ctx.fnToCall(...args)
 }
}

Быстрая реализация:

function printNameAge (argumentPassed) {
 console.log(this.name, this.age, argumentPassed)
}

let p1 = printNameAge.newBindWithoutApply({name:'foo', age: 20}, 'Without Apply Default Argument')();
Output: 'foo' 20 'Without Apply Default Argument'
let p2 = printNameAge.newBindWithoutApply({name:'bar', age: 40})('Without Apply Calling Argument');
Output: 'bar' 40 'Without Apply Calling Argument'

let p3 = printNameAge.newBindWithApply({name:'foo', age: 20}, 'With Apply Default Argument')();
Output: 'foo' 20 'With Apply Default Argument'

let p4 = printNameAge.newBindWithApply({name:'bar', age: 40})('With Apply Calling Argument');
Output: 'bar' 40 'Without Apply Calling Argument'

Точно так же Quick Polyfill для Apply может быть:

Function.prototype.myApply = function(ctx, ...args) {
  ctx.fnToCall = this;
  return ctx.fnToCall(...args)
}

Это всего лишь быстрый способ написания полифиллов. В реальном сценарии может потребоваться сделать полифилы более безопасными с помощью Object.seal () или Object.freeze ().