В этом руководстве вы узнаете о методе JavaScript call()
и о том, как использовать его более эффективно на примерах.
В JavaScript функция является экземпляром типа Function
.
Пример:
function add(x, y) { return x + y; } console.log(add instanceof Function); // true
Тип Function.prototype
имеет метод call()
со следующим синтаксисом:
functionName.call(thisArg, arg1, arg2, ...);
В этом синтаксисе метод call()
вызывает функцию functionName
с аргументами( arg1
, arg2
, …) и this
устанавливает объект thisArg
внутри функции.
thisArg
— это объект, на который ссылаетсяthis
объект внутри функцииfunctionName
.arg1
,arg2
, .. — это аргументы функции, переданные вfunctionName
.
Метод call()
возвращает результат вызова functionName()
.
В следующем примере функция add()
определяется и вызывается как обычно:
function add(x, y) { return x + y; } let result = add(10, 20); console.log(result); // 30
Следующий код вызывает функцию add()
, но вместо этого использует метод call()
:
function add(x, y) { return x + y; } let result = add.call(this, 10, 20); console.log(result); // 30
По умолчанию this
внутри функции устанавливается на глобальный объект, т. е. window
в веб-браузерах и global
в Node.js.
Обратите внимание, что в строгом режиме this
внутри функции имеет значение undefined
вместо глобального объекта.
Рассмотрим следующий пример:
var greeting = 'Hi'; var messenger = { greeting: 'Hello' } function say(name) { console.log(this.greeting + ' ' + name); }
Внутри функции say()
мы ссылаемся на greeting
через значение this
. Если вы просто вызовете функцию say()
с помощью метода call()
:
say.call(this,'John');
Он покажет следующий вывод на консоль:
"Hi John"
Однако, когда вы вызываете метод call()
объекта функции say
и передаете объект messenger
в качестве значения this
:
say.call(messenger,'John');
Вывод будет:
"Hello John"
В этом случае значение this
внутри функции say()
ссылается на объект messenger
, а не на глобальный объект.
Использование для цепочки конструкторов объекта
Вы можете использовать метод call()
для объединения конструкторов объекта. Рассмотрим следующий пример:
function Box(height, width) { this.height = height; this.width = width; } function Widget(height, width, color) { Box.call(this, height, width); this.color = color; } let widget = new Widget('red', 100, 200); console.log(widget);
Выход:
Widget { height: 'red', width: 100, color: 200 }
В этом примере:
- Во-первых, инициализируйте объект
Box
с двумя свойствами:height
иwidth
. - Во-вторых, вызовите метод
call()
объектаBox
внутри объектаWidget
, задайте значениеthis
для объектаWidget
.
Заимствование функций
В следующем примере показано, как использовать метод call() для заимствования функций:
const car = { name: 'car', start() { console.log('Start the ' + this.name); }, speedUp() { console.log('Speed up the ' + this.name); }, stop() { console.log('Stop the ' + this.name); }, }; const aircraft = { name: 'aircraft', fly() { console.log('Fly'); }, }; car.start.call(aircraft); car.speedUp.call(aircraft); aircraft.fly();
Выход:
Start the aircraft Speed up the aircraft Fly
Как это работает:
- Во-первых, определите объект
car
с одним именем свойства и тремя методами start, speedUp и stop:
const car = { name: 'car', start() { console.log('Start the ' + this.name); }, speedUp() { console.log('Speed up the ' + this.name); }, stop() { console.log('Stop the ' + this.name); }, };
- Во-вторых, определите объект
aircraft
с одним именем свойства и методом:
const aircraft = { name: 'aircraft', fly() { console.log('Fly'); }, };
- В-третьих, вызовите методы
start()
иspeedUp()
объектаcar
и методfly()
объектаaircraft
. Однако передайтеaircraft
в качестве первого аргумента в методыstart()
иspeedUp()
:
car.start.call(aircraft); car.speedUp.call(aircraft); aircraft.fly();
Внутри методов start()
и speedUp()
this
ссылается на объект aircraft
, а не на объект car
. Таким образом, this.name
возвращает 'aircraf'
. Следовательно, методы выводят следующее сообщение:
Start the aircraft Speed up the aircraft
Технически объект aircraft
заимствует методы start()
и speedUp()
объекта car
. А заимствование функций относится к объекту, который использует метод другого объекта.
В следующем примере показано, как объект arguments
заимствует метод filter()
из Array.prototype
через функцию call()
:
function isOdd(number) { return number % 2; } function getOddNumbers() { return Array.prototype.filter.call(arguments, isOdd); } let results = getOddNumbers(10, 1, 3, 4, 8, 9); console.log(results);
Выход:
[ 1, 3, 9 ]
Как это работает:
- Во-первых, определите
isOdd()
, которая возвращает true, если число является нечетным:
function isOdd(number) { return number % 2; }
- Во-вторых, определите
getOddNumbers()
, которая принимает любое количество аргументов и возвращает массив, содержащий только нечетные числа:
function getOddNumbers() { return Array.prototype.filter.call(arguments, isOdd); }
В этом примере объект arguments
заимствует метод filter() объекта Array.prototype
.
- В-третьих, вызовите
getOddNumbers()
:
let results = getOddNumbers(10, 1, 3, 4, 8, 9); console.log(results);