вопрос о функции привязки в Mozilla - PullRequest
18 голосов
/ 25 апреля 2011

У меня был вопрос о реализации функции связывания, который я нашел на сайте Mozilla. По большей части это имеет смысл для меня, но я не могу понять, для чего этот чек ...

this instanceof nop ? this : ( obj || {} ) 

в функции связывания. Очевидно, это проверка, является ли 'this' пустой функцией, но зачем вам нужно связывать пустую функцию. Я попробовал это в firebug, он работает, но какой в ​​этом смысл? Просто пытаюсь расширить мои знания JavaScript, чтобы любая помощь была бы признательна.

if ( !Function.prototype.bind ) {

  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) ) );    
    };

    nop.prototype = self.prototype;

    bound.prototype = new nop();

    return bound;
  };
}

Ответы [ 2 ]

28 голосов
/ 25 апреля 2011

Это позволяет вам вызывать связанную функцию как конструктор, не привязываясь к исходному объекту.Другими словами, «связанная» функция будет по-прежнему работать так же, как и исходная несвязанная версия, если вы вызовете ее с помощью new.

Вот пример:

var obj = {};

function foo(x) {
    this.answer = x;
}
var bar = foo.bind(obj);   // "always" use obj for "this"

bar(42);
console.log(obj.answer);   // 42

var other = new bar(1);    // Call bar as a constructor
console.log(obj.answer);   // Still 42
console.log(other.answer); // 1

Как это работает

Чтобы упростить объяснение, вот упрощенная версия кода, которая связывает только this и не обрабатывает аргументы или отсутствует параметр obj:

Function.prototype.bind = function( obj ) {
  var self = this,
  nop = function () {},
  bound = function () {
    return self.apply( this instanceof nop ? this : obj, arguments );
  };

  nop.prototype = self.prototype;
  bound.prototype = new nop();

  return bound;
};

Функция, которая возвращаетсяFunction.prototype.bind ведет себя по-разному в зависимости от того, используете ли вы его как функцию или конструктор (см. Раздел 15.3.4.5.1 и 15.3.4.5.2 Спецификации языка ECMAScript 5).Основное отличие состоит в том, что он игнорирует параметр «связанный с этим», когда он вызывается как конструктор (поскольку внутри конструктора this должен быть вновь созданным объектом).Поэтому функции bound нужен способ определить, как она вызывается.Например, bound(123) против new bound(123) и установите this соответственно.

Вот тут и появляется функция nop. По сути, она действует как промежуточный "класс", так что bound расширяется nop который расширяет self (то есть была вызвана функция bind()).Эта часть настроена здесь:

nop.prototype = self.prototype;
bound.prototype = new nop();

Когда вы вызываете связанную функцию, она возвращает это выражение:

self.apply( this instanceof nop ? this : obj, arguments ) )

this instanceof nop работает, следуя цепочке прототипов, чтобы определить, еслилюбой прототип this равен nop.prototype.При установке nop.prototype = self.prototype и bound.prototype = new nop() любой объект, созданный с помощью new bound(), будет создан с исходным прототипом от self до bound.prototype.Поэтому внутри вызова функции this instanceof nop (то есть Object.getPrototypeOf (nop) == nop.prototype) имеет значение true, и self вызывается с this (вновь созданный объект).

При обычном вызове функции 'bound ()' (без new) this instanceof nop будет ложным, поэтому obj передается как контекст this, что вы и ожидаете от связанной функции.

Причина использования промежуточной функции состоит в том, чтобы избежать вызова исходной функции (в строке bound.prototype = new nop();), что может иметь побочные эффекты.

0 голосов
/ 25 апреля 2011

Я думаю, что это короткая запись для (typeof obj != "undefined") ? obj : {}

То есть, если obj не является неопределенным, вернуть obj, иначе вернуть пустой объект ({} - пустой объект).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...