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

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

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

Следующее возвращает false, поэтому я не совсем понимаю, для чего оно используется. Какие вещи возвращают true при выполнении проверки 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;
};

person pimvdb    schedule 16.06.2011    source источник


Ответы (2)


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

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). Возможно, этого не должно быть, поэтому он был частично отредактирован. Несмотря на это, код в его нынешнем виде неверен, но будет работать до тех пор, пока вы не используете функцию в качестве конструктора.

person Matthew Crumley    schedule 17.06.2011

Кажется, в этой реализации есть ошибка. 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
person Ates Goral    schedule 16.06.2011