Apart from parameters being explicitly defined inside the function definition, there are two additional silent parameters getting passed down to the function itself. These silent parameters are called implicit parameters: this
and arguments
. They are not listed in the signature of any function but can be accessible within the function itself. The this
parameter (also called functional context), represents the object on which the function is invoked, while the arguments
parameter is an iterable representation of all the arguments passed into the function call.
Arguments parameter
Arguments parameter refers to the collection of all arguments passed to a function. Regardless of the definition of the function, we can use the arguments
parameter to access all function arguments. We don’t use the arguments parameter as widely in the new versions of the JS language. The new rest parameter handles the total collection of arguments. But it is still nice to know something about it.
The arguments parameter has a property named length
that indicates exactly how many arguments there are in the definition of the function. We can obtain individual argument values by using array indexing notation, for example, arguments[0]
to retrieve the first parameter in the list.
function testingArguments(a, b, c) { console.log(arguments.length); console.log(arguments[0]); console.log(a == arguments[0]); console.log(arguments[4]); } testingArguments(10, 'foo', true, 'fourth', 5);
We declared a function that takes three parameters, a
, b
and c
. But we invoked the same function with five arguments. Inside the function, we play around with the arguments
param, getting the length of the whole parameter (which would display 5), and getting individual elements through array notation. We even compared the variable a
to the zeroeth argument, to make sure they are the same.
Keep in mind that the arguments
parameter is not an array. Yeah, we access the element through array notation and it might have the length
property. But it is not, and most other array methods will not work on the arguments
object. The arguments parameter can access all arguments passed to the functions regardless of the declaration.
This parameter
Another implicit parameter passed to the function is the this
parameter, also known as the function context. The value of the this
parameter can be influenced by many different factors, but it most commonly points to the object that invoked the function. Knowing this is really important for JavaScript developers, and knowing how to determine where this
comes from can help with debugging.
There are four ways we can invoke functions in JavaScript:
- Regular function –
function()
- Object method –
object.function()
- Constructor –
new Car()
- Apply or call methods –
function.call(object)
orfunction.apply(object)
function regularFunction() {} function ConstructorFunction() {} let object = { objectFunction: function() {} } regularFunction(); let constructorObject = new ConstructorFunction(); object.objectFunction(); regularFunction.call(object); regularFunction.apply(object)
Let’s mention them one by one!
Function Invocation
This is the default way of invoking functions. We use the () operator and we either reference the function by a variable or call it on its own.
// 'use strict'; uncomment for this to be undefined function howMany() { console.log(this); } howMany();
When invoked in this manner the value of this
will depend on whether the script has the strict directive. If we omitted the ‘use strict’ command, the this
object would refer to the whole window
object, otherwise, it would just be – undefined
.
Object method invocation
When invoking a function that is a property of an object then the function context is the object itself. Which means that this
becomes the object itself. We can simply test this by returning “this” instead of 5 in the body of the getSpeed()
method below.
let car = { getSpeed: function() { // return this; return "5"; } } car.getSpeed();
Constructor invocation
Constructor functions behave like any other function declaration/expression, the only difference being the syntax of invocation.
function PleaseCallMe() { return this; } new PleaseCallMe();
When we invoke a new constructor function, we go through a couple of special steps, including creating a new empty object, then passing that object to the constructor as this
parameter and giving the object the function context, and in the end, the object is returned as the new
value.
The real strength of the constructor function lies right there – in the ability to create a new object and to return it as a constructor value.
function PleaseCallMe() { this.pleaseCallMeMethod = function() { return this; } } let object1 = new PleaseCallMe(); let object2 = new PleaseCallMe(); console.log(object1.pleaseCallMeMethod() == object1); console.log(object2.pleaseCallMeMethod() == object2);
Using a constructor we made sure that each invocation of the method will operate on the expected object.
Invoking with apply and call methods
We notice a common trope between the types of function invocations mentioned above. We (almost) always know what is the reference to this
. For methods we know that is the object that the method belongs to. For top-level functions, it’s either the window
object or undefined
, and for constructors it is the new object instance.
We could also explicitly give the function context to any object we want! We do this through the use of apply
and call
methods.
function sumTwoNumbers() { let sumOfNumbers = this.number1 + this.number2; return sumOfNumbers; } let objectToSum1 = { number1: 5, number2: 5 } let objectToSum2 = { number1: 2, number2: 2 } console.log(sumTwoNumbers.apply(objectToSum1)); console.log(sumTwoNumbers.apply(objectToSum2));
The apply
and call
methods are more or less similar, the only difference being the syntax. For the apply
method, we pass two parameters – the object to use as the functional context and the array of values to be used as invocation arguments. The call
method is similar, except that we pass the arguments directly.
function aboutMe(name, age) { console.log("My name is " + name + ", I am " + age +" years old. I live in " + this.city); } let personCity = { city: 'Melbourne' }; aboutMe.apply(personCity, ["John", 55]); aboutMe.call(personCity, "Jane", 21);
Look at this! Not only did we provide our arguments inside the array for the apply
method, or together with other arguments for the call
method, we also picked up the city from the function context (which is the personCity
object). The only difference between call
and apply
is the way how the arguments were supplied. Both of them take the object to use as the functional context, and then they accept one argument for apply
, or any number of arguments for call
.
Final Words
Hope you had fun reading about this
and argument
implicit parameters in JavaScript.
For more articles please click below, or check the blog.
- Largest Palindrome Product
- Largest Prime Factor
- Even Fibonacci Numbers
- Multiples of 3 or 5
- How to find the missing number in a given integer array of 1 to 100?
- Understanding Javascript prototypes
- Difference between Promise.all() and Promise.race()
- JavaScript generators
- Using this and arguments
- Arrow functions in JavaScript