Ребята могут объяснить какой-либо контекст для использования методов call
и apply
в Javascript?
Зачем использовать call
и apply
вместо прямого вызова функции?
Ребята могут объяснить какой-либо контекст для использования методов call
и apply
в Javascript?
Зачем использовать call
и apply
вместо прямого вызова функции?
Вы используете call
или apply
когда вы хотите передать другое значение this
функции. По сути, это означает, что вы хотите выполнить функцию, как если бы это был метод определенного объекта. Единственное различие между ними состоит в том, что call
ожидает параметры, разделенные запятыми, а apply
ожидает параметров в массиве.
Пример из страницы Mozilla apply
, где построены цепочки:
function Product(name, price) {
this.name = name;
this.price = price;
if (price < 0)
throw RangeError('Cannot create product "' + name + '" with a negative price');
return this;
}
function Food(name, price) {
Product.apply(this, arguments);
this.category = 'food';
}
Food.prototype = new Product();
function Toy(name, price) {
Product.apply(this, arguments);
this.category = 'toy';
}
Toy.prototype = new Product();
var cheese = new Food('feta', 5);
var fun = new Toy('robot', 40);
Что Product.apply(this, arguments)
делает следующее: конструктор Product
применяется как функция внутри каждого из конструкторов Food
и Toy
, и каждый из этих экземпляров объекта передается как this
. Таким образом, каждый из Food
и Toy
теперь имеет свойства this.name
и this.category
.
Только если вы используете call
или apply
, вы можете изменить контекст this
внутри функции.
В отличие от других языков - в JavaScript this
не относится к текущему объекту - скорее к контексту выполнения и может быть задан вызывающим.
Если вы вызываете функцию с помощью ключевого слова new
this
, это будет правильно ссылаться на новый объект (внутри функции конструктора).
Но во всех остальных случаях - this
будет ссылаться на глобальный объект, если он явно не установлен через вызов
Используется .call()
, если вы хотите заставить функцию выполнить с другим значением this
. Он устанавливает значение this
, как указано, устанавливает аргументы как указано, а затем вызывает функцию. Разница между .call()
и просто выполнением функции - это значение указателя this
, когда функция выполняется. Когда вы обычно выполняете функцию, javascript определяет, что будет указывать указатель this
(обычно глобальный контекст window
, если функция не вызывается как метод для объекта). Когда вы используете .call()
, вы точно определяете, к чему вы хотите установить this
.
Вы используете .apply()
, когда аргументы, которые вы хотите передать функции, находятся в массиве. .apply()
также может вызвать выполнение функции с определенным значением this
. .apply()
чаще всего используется, когда у вас есть неопределенное количество аргументов, исходящих из какого-то другого источника. Он часто используется, чтобы передать аргументы из одного вызова функции другому, используя специальную локальную переменную arguments
, которая содержит массив аргументов, которые были переданы вашей текущей функции.
Если у вас есть опыт работы с jQuery, вы узнаете, что большинство функций используют объект this
. Например, collection.each(function() { ... });
Внутри этой функции "this"
ссылается на объект итератора. Это одно возможное использование.
Я лично использовал .apply()
для реализации очереди запросов - я нажимаю массив аргументов в очередь, и когда придет время для его выполнения, я беру элемент и передаю его в качестве аргументов для обработчика используя .apply()
, тем самым делая код более чистым, если необходимо передать массив аргументов в качестве первого аргумента. Это еще один пример.
В общем, просто имейте в виду, что существуют способы вызова функции, и вы когда-нибудь найдете их удобными для использования для реализации вашей программы.
Я не могу придумать какую-либо нормальную ситуацию, когда настройка thisArg для чего-то другого - это цель использования apply.
Цель применения - передать массив значений функции, которая хочет эти значения в качестве аргументов.
Он был заменен в обычном повседневном использовании оператором спреда.
например.
// Finding the largest number in an array
`Math.max.apply(null, arr)` becomes `Math.max(...arr)`
// Inserting the values of one array at the start of another
Array.prototype.unshift.apply(arr1, arr2);
// which becomes
arr1 = [...arr2, ...arr1]
Если у вас есть опыт работы с Object Oriented Programming
, тогда вызов и применение будут иметь смысл, если вы сравните его с наследованием и переопределите свойства или метод/функции родительского класса из дочернего класса. Что похоже на вызов в javascript, как показано ниже:
function foo () {
this.helloworld = "hello from foo"
}
foo.prototype.print = function () {
console.log(this.helloworld)
}
foo.prototype.main = function () {
this.print()
}
function bar() {
this.helloworld = 'hello from bar'
}
// declaring print function to override the previous print
bar.prototype.print = function () {
console.log(this.helloworld)
}
var iamfoo = new foo()
iamfoo.main() // prints: hello from foo
iamfoo.main.call(new bar()) // override print and prints: hello from bar