В этом руководстве вы узнаете о типе Function
, который является типом всех функций в JavaScript.
В JavaScript все функции являются объектами. Это экземпляры типа Function
. Поскольку функции являются объектами, они имеют свойства и методы, как и другие объекты.
Свойства функций
У каждой функции есть два важных свойства: length
и prototype
.
- Свойство
length
определяет количество именованных аргументов, указанных в объявлении функции. - Свойство
prototype
ссылается на фактический объект функции.
Следующий пример:
function add(x, y) { return x + y; } console.log(add.length); // 2 console.log(add.prototype); // Object{}
Функция add()
принимает два аргумента x
и y
. Следовательно, свойство length
возвращает 2.
new.target
Как правило, вы вызываете функцию обычно следующим образом:
let result = add(10,20); console.log(result); // 30
Кроме того, вы можете вызвать функцию с ключевым словом new
в качестве конструктора:
let obj = new add(10,20);
В ES6 появилось псевдосвойство new.target
, которое позволяет определить, была ли функция или конструктор вызвана с помощью оператора new
.
Если функция вызывается нормально, new.target
не undefined
. Однако, если функция вызывается с использованием ключевого слова new
в качестве конструктора, new.target
возвращает ссылку на конструктор.
Например:
function add(x, y) { console.log(new.target); return x + y; } let result = add(10, 20); let obj = new add(10, 20);
Выход:
undefined [Function: add]
Используя new.target
, вы можете управлять тем, как будет вызываться функция.
Например, чтобы предотвратить вызов функции add()
с ключевым словом new
в качестве конструктора, вы можете получить ошибку, проверив new.target
следующим образом:
function add(x, y) { if (new.target) { throw 'The add function cannot be called as a constructor'; } return x + y; } let obj = new add(10, 20); console.log(obj);
Методы функции: apply, call и bind
Объект функции имеет три важных метода: apply()
, call()
и bind()
.
Методы apply()
и call()
Методы apply()
и call()
вызывают функцию с заданным значением this
и аргументами.
Разница между apply()
и call()
заключается в том, что вам нужно передать аргументы методу apply()
в виде объекта, подобного массиву, тогда как вы передаете аргументы функции call()
по отдельности. Например:
let cat = { type: 'Cat', sound: 'Meow' }; let dog = { type: 'Dog', sound: 'Woof' }; const say = function(message) { console.log(message); console.log(this.type + ' says ' + this.sound); }; say.apply(cat, ['What does a cat say?']); say.apply(dog, ['What does a dog say?']);
Выход:
What does a cat sound? Cat says Meow What does a dog sound? Dog says Woof
В этом примере:
- Во-первых, объявите два объекта
cat
иdog
с двумя свойствами:
let cat = { type: 'Cat', sound: 'Meow' }; let dog = { type: 'Dog', sound: 'Woof' };
- Во-вторых, определите функцию
say()
, которая принимает один аргумент:
const say = function(message) { console.log(message); console.log(this.type + ' says ' + this.sound); };
- В-третьих, вызовите функцию
say()
с помощью методаapply()
:
say.apply(cat, ['What does a cat say?']);
В этом примере первым аргументом метода apply()
является объект cat
. Следовательно, объект this
в функции say()
ссылается на объект cat
.
- В-четвертых, вызовите функцию
say()
и передайте объектdog
:
say.apply(dog, ['What does a dog say?']);
В этом примере this
в функции say()
ссылается на объект dog
.
Метод call()
аналогичен методу apply()
, за исключением способа передачи аргументов функции:
say.call(cat, 'What does a cat say?'); say.call(dog, 'What does a dog say?');
Метод bind()
Метод bind()
создает новый экземпляр функции, чье значение this
привязано к предоставленному вами объекту. Например:
Сначала определите объект с именем car
:
let car = { speed: 5, start: function() { console.log('Start with ' + this.speed + ' km/h'); } };
Затем определите другой объект с именем aircraft
:
let aircraft = { speed: 10, fly: function() { console.log('Flying'); } };
aircraft
не имеет метода start()
. Чтобы запустить aircraft
, вы можете использовать метод bind()
метода start()
объекта car
:
let taxiing = car.start.bind(aircraft);
В этом операторе мы меняем значение this
внутри метода start()
объекта car
на объект aircraft
. Метод bind()
возвращает новую функцию, назначенную переменной taxiing
.
Теперь вы можете вызвать метод start()
через переменную taxiing
:
taxiing();
Он покажет следующее сообщение:
Start with 10 km/h
Далее используется метод call()
для вызова метода start()
объекта aircraft
:
car.start.call(aircraft);
Как видите, метод bind()
создает новую функцию, которую вы можете выполнить позже, в то время как метод call()
выполняет функцию немедленно. В этом основное различие между методами bind()
и call()
.
Технически объект aircraft
заимствует метод start()
объекта car
через методы bind()
, call()
или apply()
.
По этой причине методы bind()
, call()
и apply()
также известны как функции заимствования.
Заключение
- Все функции являются экземплярами типа
Function
, то есть объектами со свойствами и методами. - У функции есть два важных свойства:
name
иprototype
. - У функции также есть три важных метода:
call()
,apply()
иbind()
.