Причина использования функции instanceof() {} '?

В Mozilla Developer Center есть страница о Function.prototype.bind и предоставляет функцию совместимости для браузеров, которые не поддерживают эту функцию.

Однако при анализе этого кода совместимости я не могу понять, почему они используют instanceof nop. nop установлено значение function() {}. Какая часть спецификации ECMA на bind соответствует ли это? И какие переменные являются экземпляром function() {}?

Следующее возвращает false, поэтому я не совсем понимаю, для чего он используется. Какие вещи верны при выполнении проверки instanceof function() {}?

(function() {}) instanceof (function() {}) // false

Код выглядит следующим образом:

Function.prototype.bind = function( obj ) {
    if(typeof this !== 'function')
      throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');

    var slice = [].slice,
        args = slice.call(arguments, 1), 
        self = this, 
        nop = function () {}, 
        bound = function () {
          return self.apply( this instanceof nop ? this : ( obj || {} ), 
                              args.concat( slice.call(arguments) ) );    
        };

    bound.prototype = this.prototype;

    return bound;
};

Ответы

Ответ 1

Кто-то отредактировал часть, которая делает ее полезной. Вот как оно выглядит:

Function.prototype.bind = function( obj ) {
    var slice = [].slice,
    args = slice.call(arguments, 1), 
    self = this, 
    nop = function () {}, 
    bound = function () {
        return self.apply( this instanceof nop ? this : ( obj || {} ), 
                            args.concat( slice.call(arguments) ) );    
    };

    // These lines are the important part
    nop.prototype = self.prototype;
    bound.prototype = new nop();

    return bound;
};

Я ответил на другой вопрос, который задавал одно и то же (но когда код был прав) здесь: вопрос функции привязки mozilla.

Причина проверки this instanceof nop заключается в том, что если вы вызываете связанную функцию как конструктор (т.е. с оператором new), this привязан к новому объекту, а не к тому, что вы передали в bind.

Чтобы объяснить "важную часть", nop в основном вставляется в цепочку прототипов, поэтому при вызове функции как конструктора this есть экземпляр nop.

Итак, если вы запустите var bound = original.bind(someObject);, цепочка прототипов будет выглядеть так:

  original
     |
    nop
     |
   bound

Мое предположение, почему они использовали nop вместо this instanceof self, так это, чтобы связанная функция имела собственное свойство prototype (которое наследуется от self 's). Возможно, это не предполагало, почему это было частично отредактировано. Независимо от того, что код, как сейчас, неверен, но будет работать до тех пор, пока вы не используете эту функцию в качестве конструктора.

Ответ 2

Кажется, что ошибка с этой реализацией. nop никогда не используется (для создания экземпляра чего-либо) для этой проверки instanceof, которая никогда не может быть истинна ни для чего, поскольку никакой объект не может быть создан из nop, который глубоко скрыт в этом закрытии.

Рассмотрим это:

// Identical definition, but different Function instances
var nop = function () {},
    mop = function () {};

var obj1 = new mop;

obj1 instanceof mop // true
obj1 instanceof nop // false