Call function using javascript

Function.prototype.call()

The call() method calls the function with a given this value and arguments provided individually.

Try it

Syntax

call(thisArg) call(thisArg, arg1) call(thisArg, arg1, /* …, */ argN) 

Parameters

The value to use as this when calling func . If the function is not in strict mode, null and undefined will be replaced with the global object, and primitive values will be converted to objects.

Arguments for the function.

Return value

The result of calling the function with the specified this value and arguments.

Description

Note: This function is almost identical to apply() , except that the function arguments are passed to call() individually as a list, while for apply() they are combined in one object, typically an array — for example, func.call(this, «eat», «bananas») vs. func.apply(this, [«eat», «bananas»]) .

Normally, when calling a function, the value of this inside the function is the object that the function was accessed on. With call() , you can assign an arbitrary value as this when calling an existing function, without first attaching the function to the object as a property. This allows you to use methods of one object as generic utility functions.

Читайте также:  Mutable collections in java

Warning: Do not use call() to chain constructors (for example, to implement inheritance). This invokes the constructor function as a plain function, which means new.target is undefined , and classes throw an error because they can’t be called without new . Use Reflect.construct() or extends instead.

Examples

Using call() to invoke a function and specifying the this value

In the example below, when we call greet , the value of this will be bound to object obj , even when greet is not a method of obj .

function greet()  console.log(this.animal, "typically sleep between", this.sleepDuration); > const obj =  animal: "cats", sleepDuration: "12 and 16 hours", >; greet.call(obj); // cats typically sleep between 12 and 16 hours 

Using call() to invoke a function without specifying the first argument

If the first thisArg parameter is omitted, it defaults to undefined . In non-strict mode, the this value is then substituted with globalThis (which is akin to the global object).

.globProp = "Wisen"; function display()  console.log(`globProp value is $this.globProp>`); > display.call(); // Logs "globProp value is Wisen" 

In strict mode, the value of this is not substituted, so it stays as undefined .

"use strict"; globalThis.globProp = "Wisen"; function display()  console.log(`globProp value is $this.globProp>`); > display.call(); // throws TypeError: Cannot read the property of 'globProp' of undefined 

Transforming methods to utility functions

call() is almost equivalent to a normal function call, except that this is passed as a normal parameter instead of as the value that the function was accessed on. This is similar to how general-purpose utility functions work: instead of calling array.map(callback) , you use map(array, callback) , which avoids mutating Array.prototype , and allows you to use map with array-like objects that are not arrays (for example, arguments ).

Take Array.prototype.slice() , for example, which you want to use for converting an array-like object to a real array. You could create a shortcut like this:

const slice = Array.prototype.slice; // . slice.call(arguments); 

Note that you can’t save slice.call and call it as a plain function, because the call() method also reads its this value, which is the function it should call. In this case, you can use bind() to bind the value of this for call() . In the following piece of code, slice() is a bound version of Function.prototype.call() , with the this value bound to Array.prototype.slice() . This means that additional call() calls can be eliminated:

// Same as "slice" in the previous example const unboundSlice = Array.prototype.slice; const slice = Function.prototype.call.bind(unboundSlice); // . slice(arguments); 

Specifications

Browser compatibility

BCD tables only load in the browser

See also

Found a content problem with this page?

This page was last modified on Jun 1, 2023 by MDN contributors.

Your blueprint for a better internet.

MDN

Support

Our communities

Developers

Visit Mozilla Corporation’s not-for-profit parent, the Mozilla Foundation.
Portions of this content are ©1998– 2023 by individual mozilla.org contributors. Content available under a Creative Commons license.

Источник

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

Материал на этой странице устарел, поэтому скрыт из оглавления сайта.

Более новая информация по этой теме находится на странице https://learn.javascript.ru/call-apply-decorators.

Итак, мы знаем, что this – это текущий объект при вызове «через точку» и новый объект при конструировании через new .

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

Метод call

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

При этом вызывается функция func , первый аргумент call становится её this , а остальные передаются «как есть».

Вызов func.call(context, a, b. ) – то же, что обычный вызов func(a, b. ) , но с явно указанным this(=context) .

Например, у нас есть функция showFullName , которая работает с this :

Пока объекта нет, но это нормально, ведь JavaScript позволяет использовать this везде. Любая функция может в своём коде упомянуть this , каким будет это значение – выяснится в момент запуска.

Вызов showFullName.call(user) запустит функцию, установив this = user , вот так:

function showFullName() < alert( this.firstName + " " + this.lastName ); >var user = < firstName: "Василий", lastName: "Петров" >; // функция вызовется с this=user showFullName.call(user) // "Василий Петров"

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

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

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

При помощи call можно легко взять метод одного объекта, в том числе встроенного, и вызвать в контексте другого.

Это называется «одалживание метода» (на англ. method borrowing).

Используем эту технику для упрощения манипуляций с arguments .

Как мы знаем, arguments не массив, а обычный объект, поэтому таких полезных методов как push , pop , join и других у него нет. Но иногда так хочется, чтобы были…

Нет ничего проще! Давайте скопируем метод join из обычного массива:

function printArgs() < arguments.join = [].join; // одолжили метод (1) var argStr = arguments.join(':'); // (2) alert( argStr ); // сработает и выведет 1:2:3 >printArgs(1, 2, 3);
  1. В строке (1) объявлен пустой массив [] и скопирован его метод [].join . Обратим внимание, мы не вызываем его, а просто копируем. Функция, в том числе встроенная – обычное значение, мы можем скопировать любое свойство любого объекта, и [].join здесь не исключение.
  2. В строке (2) запустили join в контексте arguments , как будто он всегда там был.

Здесь метод join массива скопирован и вызван в контексте arguments . Не произойдёт ли что-то плохое от того, что arguments – не массив? Почему он, вообще, сработал?

Ответ на эти вопросы простой. В соответствии со спецификацией, внутри join реализован примерно так:

function join(separator) < if (!this.length) return ''; var str = this[0]; for (var i = 1; i < this.length; i++) < str += separator + this[i]; >return str; >

Как видно, используется this , числовые индексы и свойство length . Если эти свойства есть, то все в порядке. А больше ничего и не нужно.

В качестве this подойдёт даже обычный объект:

var obj = < // обычный объект с числовыми индексами и length 0: "А", 1: "Б", 2: "В", length: 3 >; obj.join = [].join; alert( obj.join(';') ); // "A;Б;В"

…Однако, копирование метода из одного объекта в другой не всегда приемлемо!

Представим на минуту, что вместо arguments у нас – произвольный объект. У него тоже есть числовые индексы, length и мы хотим вызвать в его контексте метод [].join . То есть, ситуация похожа на arguments , но (!) вполне возможно, что у объекта есть свой метод join .

Поэтому копировать [].join , как сделано выше, нельзя: если он перезапишет собственный join объекта, то будет страшный бардак и путаница.

Безопасно вызвать метод нам поможет call :

function printArgs() < var join = [].join; // скопируем ссылку на функцию в переменную // вызовем join с this=arguments, // этот вызов эквивалентен arguments.join(':') из примера выше var argStr = join.call(arguments, ':'); alert( argStr ); // сработает и выведет 1:2:3 >printArgs(1, 2, 3);

Мы вызвали метод без копирования. Чисто, безопасно.

Ещё пример: [].slice.call(arguments)

В JavaScript есть очень простой способ сделать из arguments настоящий массив. Для этого возьмём метод массива: slice.

По стандарту вызов arr.slice(start, end) создаёт новый массив и копирует в него элементы массива arr от start до end . А если start и end не указаны, то копирует весь массив.

Вызовем его в контексте arguments :

function printArgs() < // вызов arr.slice() скопирует все элементы из this в новый массив var args = [].slice.call(arguments); alert( args.join(', ') ); // args - полноценный массив из аргументов >printArgs('Привет', 'мой', 'мир'); // Привет, мой, мир

Как и в случае с join , такой вызов технически возможен потому, что slice для работы требует только нумерованные свойства и length . Всё это в arguments есть.

Метод apply

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

Вызов функции при помощи func.apply работает аналогично func.call , но принимает массив аргументов вместо списка.

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

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

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

Преимущество apply перед call отчётливо видно, когда мы формируем массив аргументов динамически.

Например, в JavaScript есть встроенная функция Math.max(a, b, c. ) , которая возвращает максимальное значение из аргументов:

При помощи 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 .

Но в данном случае в качестве контекста можно передавать что угодно, поскольку в своей внутренней реализации метод Math.max не использует this . Действительно, зачем this , если нужно всего лишь выбрать максимальный из аргументов? Вот так, при помощи apply мы получили короткий и элегантный способ вычислить максимальное значение в массиве!

В современном стандарте call/apply передают this «как есть». А в старом, без use strict , при указании первого аргумента null или undefined в call/apply , функция получает this = window , например:

Источник

JavaScript Function call()

With the call() method, you can write a method that can be used on different objects.

All Functions are Methods

In JavaScript all functions are object methods.

If a function is not a method of a JavaScript object, it is a function of the global object (see previous chapter).

The example below creates an object with 3 properties, firstName, lastName, fullName.

Example

const person = <
firstName:»John»,
lastName: «Doe»,
fullName: function () <
return this.firstName + » » + this.lastName;
>
>

// This will return «John Doe»:
person.fullName();

In the example above, this refers to the person object.

this.firstName means the firstName property of this.

this.firstName means the firstName property of person.

What is this?

In JavaScript, the this keyword refers to an object.

Which object depends on how this is being invoked (used or called).

The this keyword refers to different objects depending on how it is used:

In an object method, this refers to the object.
Alone, this refers to the global object.
In a function, this refers to the global object.
In a function, in strict mode, this is undefined .
In an event, this refers to the element that received the event.
Methods like call() , apply() , and bind() can refer this to any object.

Note

See Also:

The JavaScript call() Method

The call() method is a predefined JavaScript method.

It can be used to invoke (call) a method with an owner object as an argument (parameter).

With call() , an object can use a method belonging to another object.

This example calls the fullName method of person, using it on person1:

Example

const person = <
fullName: function() <
return this.firstName + » » + this.lastName;
>
>
const person1 = <
firstName:»John»,
lastName: «Doe»
>
const person2 = <
firstName:»Mary»,
lastName: «Doe»
>

// This will return «John Doe»:
person.fullName.call(person1);

This example calls the fullName method of person, using it on person2:

Example

const person = <
fullName: function() <
return this.firstName + » » + this.lastName;
>
>
const person1 = <
firstName:»John»,
lastName: «Doe»
>
const person2 = <
firstName:»Mary»,
lastName: «Doe»
>

// This will return «Mary Doe»
person.fullName.call(person2);

The call() Method with Arguments

The call() method can accept arguments:

Example

const person = <
fullName: function(city, country) <
return this.firstName + » » + this.lastName + «,» + city + «,» + country;
>
>

const person1 = firstName:»John»,
lastName: «Doe»
>

person.fullName.call(person1, «Oslo», «Norway»);

Источник

Оцените статью