8.7.3. Методы call() и apply()

We use cookies. Read the Privacy and Cookie Policy

Методы саll() и аррlу() позволяют выполнять косвенный вызов функции (раздел 8.2.4), как если бы она была методом некоторого другого объекта. (Мы уже использовали метод саll() в примере 6.4 для вызова Object.prototype.toString относительно объекта, класс которого необходимо было определить.) Первым аргументом обоим методам, саll() и аррlу(), передается объект, относительно которого вызывается функция; этот аргумент определяет контекст вызова и становится значением ключевого слова this в теле функции. Чтобы вызвать функцию f() (без аргументов) как метод объекта о, можно использовать любой из методов, саll() или аррlу():

f.call(о);

f.apply(o);

Любой из этих способов вызова эквивалентен следующему фрагменту (где предполагается, что объект о не имеет свойства с именем m):

о.m = f; // Временно сделать f методом о.

о.m(); // Вызывать его без аргументов,

delete о.m; // Удалить временный метод.

В строгом режиме ECMAScript 5 первый аргумент методов саll() и apply() становится значением this, даже если это простое значение, null или undefined. В ECMAScript 3 и в нестрогом режиме значения null и undefined замещаются глобальным объектом, а простое значение - соответствующим объектом-оберткой.

Все остальные аргументы метода саll(), следующие за первым аргументом, определяющим контекст вызова, передаются вызываемой функции. Например, ниже показано, как можно передать функции f() два числа и вызвать ее, как если бы она была методом объекта о:

f.call(o, 1, 2);

Метод аррlу() действует подобно методу саll(), за исключением того, что аргументы для функции передаются в виде массива:

f.apply(o, [1,2]);

Если функция способна обрабатывать произвольное число аргументов, метод apply() может использоваться для вызова такой функции в контексте массива произвольной длины. Например, чтобы отыскать наибольшее число в массиве чисел, для передачи элементов массива функции Math.max() можно было бы использовать метод ар ply ():

var biggest = Math.max.apply(Math, array_of_numbers);

Обратите внимание, что метод apply() может работать не только с настоящими массивами, но и с объектами, подобными массивам. В частности, вы можете вызвать функцию с теми же аргументами, что и текущую функцию, передав массив с аргументами непосредственно методуаррlу(). Этот прием демонстрируется ниже:

// Замещает метод m объекта о версией метода, которая регистрирует

// сообщения до и после вызова оригинального метода.

function trace(o, m) {

  var original = o[m]; // Сохранить оригинальный метод в замыкании.

  o[m] = function() { // Определить новый метод.

    console.log(new Date(), "Entering:", m); // Записать сообщение,

    var result = original.apply(this, arguments): // Вызвать оригинал,

    console.log(new Date(), "Exiting:", m); // Записать сообщение,

    return result: // Вернуть результат.

  };

}

Эта функция trace() принимает объект и имя метода. Она замещает указанный метод новым методом, который «обертывает» оригинальный метод дополнительной функциональностью. Такой прием динамического изменения существующих методов иногда называется «обезьяньей заплатой» («monkey-patching»).