Причина использования instanceof function () {} '? - PullRequest
15 голосов
/ 16 июня 2011

В Центре разработчиков 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;
};

Ответы [ 2 ]

8 голосов
/ 17 июня 2011

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

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

3 голосов
/ 16 июня 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
...