Книга: JavaScript. Подробное руководство, 6-е издание

8.7.4. Метод bind()

8.7.4. Метод bind()

Метод bind() впервые появился в ECMAScript 5, но его легко имитировать в ЕСМА-Script 3. Как следует из его имени, основное назначение метода bind() состоит в том, чтобы связать (bind) функцию с объектом. Если вызвать метод bind() функции f и передать ему объект о, он вернет новую функцию. Вызов новой функции (как обычной функции) выполнит вызов оригинальной функции f как метода объекта о. Любые аргументы, переданные новой функции, будут переданы оригинальной функции. Например:

function f(у) { return this.x + у: } // Функция, которую требуется привязать
var о = { х : 1 }; // Объект, к которому выполняется привязка
var g = f.bind(o); // Вызов g(х) вызовет o.f(x)
g(2) // => 3

Такой способ связывания легко реализовать в ECMAScript 3, как показано ниже:

// Возвращает функцию, которая вызывает f как метод объекта о
// и передает ей все свои аргументы,
function bind(f, о) {
   if (f.bind) return f.bind(o): // Использовать метод bind, если имеется
   else return function() { // Иначе связать, как показано ниже
            return f.apply(o, arguments):
  };
}

Метод bind() в ECMAScript 5 не просто связывает функцию с объектом. Он также выполняет частичное применение: помимо значения this связаны будут все аргументы, переданные методу bind() после первого его аргумента. Частичное применение - распространенный прием в функциональном программировании и иногда называется каррингом (currying). Ниже приводится несколько примеров использования метода bind() для частичного применения:

var sum = function(x,у) { return х + у }; // Возвращает сумму 2 аргументов
// Создать новую функцию, подобную sum, но со связанным значением null
// ключевого слова this и со связанным значением первого аргумента, равным 1.
// Новая функция принимает всего один аргумент,
var succ = sum.bind(null, 1);
succ(2) // => 3: аргумент x связан со значением 1, а 2 передается в арг. у
function f(y.z) { return this.x + у + z }; // Еще одна функция сложения
var g = f.bind({x:1}, 2); // Связать this и у
g(3)     // => 6: this.x - связан с 1, у - связан с 2, а 3 передается в z

В ECMAScript 3 также возможно связывать значение this и выполнять частичное применение. Стандартный метод bind() можно имитировать программным кодом, который приводится в примере 8.5. Обратите внимание, что этот метод сохраняется как Function.prototype.bind, благодаря чему все функции наследуют его. Данный прием подробно рассматривается в разделе 9.4.

Пример 8.5. Метод Function.bind() для ECMAScript 3

if (!Function.prototype.bind) {
Function.prototype.bind = function(o /*, аргументы */) {
    // Сохранить this и arguments в переменных, чтобы их можно было
    // использовать во вложенной функции ниже,
    var self = this, boundArgs = arguments;
    // Возвращаемое значение метода bind() - функция
    return function() {
      // Сконструировать список аргументов, начиная со второго аргумента
      // метода bind, и передать все эти аргументы указанной функции,
      var args = [], і;
      fог(і = 1; і < boundArgs.length; i++) args.push(boundArgs[i]);
      for(i = 0; і < arguments.length; i++) args.push(arguments[i]);
      // Теперь вызвать self как метод объекта о со всеми аргументами
      return self.apply(о, args);
    };
  };
}

Обратите внимание, что функция, возвращаемая этим методом bind(), является замыканием, использующим переменные self и boundArgs, объявленные во внешней функции, которые остаются доступными вложенной функции даже после того, как она будет возвращена внешней функцией и вызвана из-за пределов внешней функции.

Метод bind(), определяемый стандартом ECMAScript 5, имеет некоторые особенности, которые невозможно реализовать в ECMAScript 3. Прежде всего, настоящий метод bind() возвращает объект функции, свойство length которой установлено в соответствии с количеством параметров связываемой функции, минус количество связанных аргументов (но не меньше нуля). Во-вторых, метод bind() в ECMAScript 5 может использоваться для частичного применения функций-конструкторов. Если функцию, возвращаемую методом bind(), использовать как конструктор, значение this, переданное методу bind(), игнорируется, и оригинальная функция будет вызвана как конструктор, с уже связанными аргументами, если они были определены. Функции, возвращаемые методом bind(), не имеют свойства prototype (свойство prototype обычных функций нельзя удалить), и объекты, созданные связанными функциями-конструкторами, наследуют свойство prototype оригинального, несвязанного конструктора. Кроме того, с точки зрения оператора instanceof связанные конструкторы действуют точно так же, как несвязанные конструкторы.

Оглавление книги


Генерация: 0.122. Запросов К БД/Cache: 2 / 0
поделиться
Вверх Вниз