Явное указание this: методы «call», «apply»

Явное указание this: методы «call», «apply»

Здравствуйте! Мы уже с вами в прошлом уроке  рассмотрели указатель  this –  и выяснили, что это текущий объект при вызове «через точку» и соответственно  новый объект при конструировании через new.

В этом  уроке наша задача состоит в том, что  получить окончательное и полное понимание об объекте  this в JavaScript.  Для этого не хватает самого малого: способа явно указать this  с помощью  call и apply.

методы call и apply javascript

Метод call

Вот синтаксис этого метода:

func.call(context, arg1, arg2, ...)

При этом будет вызвана функция func, первый аргумент call станет её this, а остальные будут переданы «как есть».
Вызов func.call(context, a, b…) – то же, что и обычный вызов func(a, b…), но с явно указанным указателем this(=context).
Например, если у вас есть функция showName, которая будет работать с this:

function showName() {
  alert( this.firstName + " " + this.lastName );
}

Пока объекта как видите нет, но в принципе это нормально, ведь JavaScript позволяет использовать указатель this везде. Любая функция может упомянуть this, а вот каким будет это значение – и выяснится в момент запуска функции.
Вызов showName.call(user) запустит функцию, установив соответственно this = user, вот так:

function showName() {
  alert( this.firstName + " " + this.lastName );
}

var user = {
  firstName: "Вася",
  lastName: "Васин"
};
// функция будет вызвана с this=user
showame.call(user) // "Вася Васин"

После контекста в call следует передавать аргументы для функции. Давайте рассмотрим более сложный вариант showName, который будет конструировать ответ из указанных свойств объекта:

var user = {
  firstName: "Вася",
  surname: "Петров",
  patronym: "Петрович"
};
function showName(firstPart, lastPart) {
  alert( this[firstPart] + " " + this[lastPart] );
}
// f.call(контекст, аргумент1, аргумент2, ...)
showFullName.call(user, 'firstName', 'surname') // "Вася Петров"
showFullName.call(user, 'firstName', 'patronym') // "Вася Петрович"

«Одалживание метода»

При помощи call можно вызывать один метод в контексте другого.
Это называется как «одалживание метода»
Давайте используем эту технику для упрощения манипуляций с arguments.
Как вы знаете, arguments вовсе не массив, а объект, поэтому таких методов как push, pop, join и др. у него нет. Но иногда бывают случаи чтобы были…

function printArgs() {
  arguments.join = [].join; // одолжим метод 
  var arg = arguments.join(':'); // (2)
  alert( arg ); // сработает и выведет 1:2:3
}
printArgs(1, 2, 3);
  1. В строке (1) был объявлен пустой массив [] и соответственно скопирован его метод [].join. Обратите внимание, мы не вызывали его, а просто скопировали.
  2. А в строке (2) запустили join уже в контексте arguments.

 

Читайте также  Объекты. Как создать объект в JavaScript.

Метод apply

Если вам неизвестно, с каким количеством аргументов нужно вызвать функцию, можно использовать и  более мощный метод: apply.
Если вызвать функцию при помощи func.apply  она  сработает аналогично func.call, но принимает массив аргументов вместо списка это и есть основное отличие.

func.call(context, arg1, arg2);
// будет идентичен вызову
func.apply(context, [arg1, arg2]);

А в частности, эти 2 строчки сработают одинаково:

showName.call(user, 'firstName', 'surname');
showName.apply(user, ['firstName', 'surname']);

Преимущество apply перед call будет заметно если массив аргументов будет сформирован динамически.
Например, в JavaScript есть встроенный метод Math.max(a, b, c…), который находит максимальное значение из переданных аргументов.

alert( Math.max(1, 5, 2) ); // 5

При помощи apply мы можем найти максимум в произвольном массиве, вот так:

var arr = [];
arr.push(1);
arr.push(5);
arr.push(2);
// получить максимум из элементов arr
alert( Math.max.apply(null, arr) ); // 5

В примере мы передаем аргументы через массив – второй параметр apply… А вот в качестве контекста this был передан null.
Полный эквивалент вызову Math.max(1,2,3) мог быть вызов Math.max.apply(Math, [1,2,3]). И в обоих этих вызовах контекстом будет объект Math.

Итоги про this

Значение указателя this устанавливается в зависимости от того, как вызвана функция:

  • При вызове функции как метода:
    obj.func(...)    // this = obj
    obj["func"](...)

При  вызове функции как функции:

func(...) // this = window (ES3) /undefined (ES5)

В new:

new func() // this = {} (новый объект)

Ну и явное указание:

func.apply(context, args) // this = context (явная передача)
func.call(context, arg1, arg2, ...)

Задания

Перепишите функцию суммирования аргументов

Есть например функция summa, которая суммирует все элементы массива:

function summa(arr) {
  return arr.reduce(function(a, b) {
    return a + b;
  });
}
alert( summa([1, 2, 3]) ); // 6 (=1+2+3)

Создайте аналогичную функцию summaArgs(), которая будет суммировать все свои аргументы:
Для решения вам надо применить метод reduce к arguments, используя call, apply или одалживание метода.

Читайте также  Расширение объектов. Свойство Prototype

Применитm функцию к аргументам

Напишите функцию applyAll(func, arg1, arg2…), которая будет получать функцию func и любое произвольное количество аргументов.
Она дожна вызвать func(arg1, arg2…), то есть передать в func все аргументы, начиная со второго, и возвращать результат.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Плюсануть
Поделиться

Об авторе

admin administrator

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: