Книга: JavaScript. Подробное руководство, 6-е издание
8.7.3. Методы call() и apply()
8.7.3. Методы call() и apply()
Методы са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»).
- Элемент xsl:call-template
- 2. How to Apply These Terms to Your New Programs
- Mounting Automatically with
- 5.4.1. The *__initcall Macros
- 5.5.1. Initialization via initcalls
- 16.3.3. Machine-Dependent Calls
- 2.4. REMOTE PROCEDURE CALL
- 7.5.1. Remote Procedure Call
- 9.2.5. Kernel Calls for Process Management
- 9.3.4. Kernel Calls for Memory Management
- 9.4.4. Kernel Calls for Communication
- 10.2.4. Thread Calls