Подтвердить что ты не робот

Если мы polyfill fn.bind() в JavaScript, почему вы должны проверить тип "this"?

Я вижу в Mozilla polyfill fn.bind() следующим образом:

if (!Function.prototype.bind) {

  Function.prototype.bind = function(oThis) {

    if (typeof this !== 'function') {
      // closest thing possible to the ECMAScript 5
      // internal IsCallable function
      throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
    }

    // other code omitted here...

  };
}

Я не понимаю, почему мы должны проверять тип this... потому что, если мы говорим, что fn.bind() и fn - это функция, то она будет работать, а если fn не является функции, то fn.bind никогда не достигнет Function.prototype.bind прототипом наследования. Итак, почему мы должны проверять тип this?

4b9b3361

Ответ 1

если fn не является функцией, то fn.bind никогда не достигнет Function.prototype.bind прототипным наследованием.

Правда, однако это не единственный способ this. Например, если мы должны использовать методы .call или .apply в самой функции bind или сделать что-то действительно сумасшедшее, как назначить его другим объектам, оно будет отличаться от нативной функции.

Учитывая следующий код, используя собственный метод ES5:

var notAFunction = {};
var someObject = {};

Function.prototype.bind.call(notAFunction, someObject);

Ответ 2

Не все вызываемые объекты наследуют (или равны) Function.prototype. Например:

typeof document.createElement('object') === "function"; // true
document.createElement('object') instanceof Function; // false

И даже объекты, которые наследуют от Function.prototype, могут иметь bind shadowed:

var f = function() {};
f.bind = 123;
f.bind === Function.prototype.bind; // false

Однако вы можете захотеть позвонить Function.prototype.bind на эти вызываемые объекты. Поэтому у нас есть такие вещи, как Function.prototype.call, Function.prototype.apply или Reflect.apply. Вы можете использовать их для вызова bind на любом объекте, независимо от того, является он вызываемым или нет.

Также возможен обратный. У вас может быть объект, который наследуется от Function.prototype и не может быть вызван. Например:

Object.create(Function.prototype) instanceof Function; // true
typeof Object.create(Function.prototype) === "function"; // false

Поэтому вы не можете делать никаких предположений. Если вы хотите, чтобы polyfill соответствовал ES5, вы должны проверить, является ли объект вызываемым. В ES5 проверка того, что typeof возвращает "function", делает именно это (но в ES3 он может не работать для объектов хоста).