В этом руководстве вы узнаете о методе 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);
