## Introduction

As we learnt in the previous chapter, function are an extremely useful feature of programming. And to functions, what's a lot useful is the idea of parameters and arguments.

JavaScript provides quite a decent amount of utilities and notations to work with parameters and arguments in various ways. Some are quite old and supported to date, while some are pretty recent and elegant in accomplishing the same things the old utilities are capable of.

In particular, we'll cover the `arguments` object in detail, and reference about its internal implementation from the ECMAScript spec; consider default-valued parameters, rest parameters and much more.

Let's start exploring...

## The arity of a function

In mathematics and programming, a function's arity refers to the number of parameters defined in function.

In the case of functions in JavaScript, arity refers to the number of parameters given in the function's definition, excluding default-valued, rest and destructured parameters.

We'll cover all these three classifications of parameters later on in this very chapter.

In the code below, we define a function `sum()` with two parameters `a` and `b`:

``````function sum(a, b) {
return a + b;
}``````

What do you think would be the arity of `sum()`? Well, there are two parameters, likewise the arity is 2.

Similarly, below we define a function with three parameters `b`, `n` and `m`, and hence an arity of 3:

``````function modExp(b, n, m) {
return (b ** n) % m;
}``````

Here, `modExp()` represents the modular exponentiation operation used in computer science, particularly in cryptography.

Now in both the code snippets above, we are determining the arity of the given function ourself by reading the source code. It would've been much better if we could programmatically retrieve this value.

Well, it turns out that there is a way and it's very simple!

To inspect the arity of given function in JavaScript, we access its `length` property.

As stated before, the `length` property would only consider non-rest, non-default-valued, and non-destructed parameters of a given function.

Let's try accessing `length` for both the functions given above.

First for the `sum()` function:

``````function sum(a, b) {
return a + b;
}

console.log('Arity:', sum.length);``````
Arity: 2

Now, for the `modExp()` function:

``````function modExp(b, n, m) {
return (b ** n) % m;
}

console.log(modExp.length);``````
Arity: 3

Amazing. Just as we expected.

In practical JavaScript code, we might not need to know the arity of given functions very often. But if we ever do need to, we'd know what property to use.

## The `arguments` object

Often times, we're more interested in figuring out the number of arguments actually passed into a function when invoking it. This couldn't always reliably be done by the function's `length` property.

For instance, consider the definition of `sum()` below:

``````function sum(a, b) {
console.log('Arity within the function:', sum.length);
return a + b;
}

sum(10, 20, 30);

console.log('Arity outside the function:', sum.length);``````
Arity within the function: 2
Arity outside the function: 2

The function clearly has an arity of 2, likewise `sum.length` always gives `2`, whether we access the property outside the function, or within the function. But notice that when we invoke `sum()` in line 6, we actually pass in 3 arguments.

JavaScript provides an array-like object to all functions, excluding arrow functions, which could be used to inspect the total number of arguments passed to them, regardless of the fact that those arguments actually align with given parameters.

That is the `arguments` object.

`arguments` is a local variable created every time a function is called. It points to an array-like object that holds the list of all arguments passed into the function.

It looks and works just like an array i.e. has indexed elements starting at the index `0` and a `length` property to denote the total number of elements, and is therefore termed as 'array-like'.

However, keep in mind that `arguments` is not actually an array. We couldn't call array methods such as `slice()`, `sort()`, `push()` etc. on it.

Let's see what `arguments` looks like:

First, we'll inspect the `arguments` object as it is and see its structure:

``````function f() {
console.log(arguments);
}

f(10);
f(10, 'Hello World!');
f(10, 20, 'Hello World!');
f(true, false, 50, 40, 30);``````
``Arguments [10, ...]``
``Arguments [10, 'Hello World!', ...]``
``Arguments [10, 20, 'Hello World!', ...]``
``Arguments [true, false, 50, 40, 30, ...]``
The `...` in the code above represents other properties on the `arguments` object. Try executing the code above in the console window, and see the output.

Let's see `arguments` in some real action.

Consider the extended definition of `sum()` below:

``````function sum(a, b) {
if (arguments.length === 3) return a + b + arguments;
return a + b;
}

console.log(sum(10, 20));
console.log(sum(10, 20, 50));
console.log(sum(10, 20, 50, 60));``````
30
80
30

When the function is called, we check the number of args passed to it. If 3 args are given, we add them all together and return the sum. Note that the third argument doesn't have a corresponding parameter, likewise to access it we have to use `arguments`.

However, if the number of args is not equal to 3, we just return the sum of the first two arguments.

This definition of `sum()` is definitely a bit more flexible than the last definition that was capable of adding only two args. But it's still not that flexible. We could pass in 4, or more, args whereby only the first two would be considered.

A much more robust definition of `sum()` would require iterating over all elements in `arguments` and adding them together. There are multiple ways of performing this iteration — using the `for` loop, or array methods such as `forEach()` and `reduce()` with a clever trick.

We'll see this trick in the chapter JavaScript Function Methods.

One important thing to note in the code above is that we refer to the first 2 args of `sum()` by the names `a` and `b` respectively; not as `arguments` and `arguments`. The latter is also possible.

An illustration is shown below:

``````function sum(a, b) {
if (arguments.length === 3) {
return arguments + arguments + arguments;
}
return arguments + arguments;
}

console.log(sum(10, 20));
console.log(sum(10, 20, 50));
console.log(sum(10, 20, 50, 60));``````
30
80
30

This definition is exactly the same as before, except for that now instead of `a` and `b`, we use `arguments` and `arguments`, respectively.

#### Exotic arguments object

According to the ECMAScript spec, when a function created using the `function` keyword is in non-strict mode, and doesn't have any modern ES6-style parameters, the `arguments` object created for it is called an exotic arguments object.

It works a bit differently than an ordinary arguments object. We'll get to the latter very shortly; first let's see what exactly is so special about an exotic arguments object.

When a function is invoked, all the parameters, that have been provided with arguments, are linked with corresponding entries in `arguments`, if the object is an exotic arguments object.

This merely means that if we change one, the other is changed automatically.

Didn't understand a word? Well, let's consider an example to help understand the definition above.

Below we have a simple function `f()` which is called on the next line after being declared:

``````function f(a) {
a = 'new';

console.log(a);
console.log('arguments:', arguments);
}

f('old');``````

Inside the function, in line 2, we change the value of the parameter `a` and then inspect both `a` and `arguments`. `a` would obviously change, but the most interesting thing is that `arguments` changes as well.

What happens internally is as follows:

When the function `f()` is invoked, the `arguments` object is created containing all the arguments passed in `f('old')` — in this case, the arg `'old'`. Then, each item in this list is linked with the corresponding parameter in the function's definition.

In this case, this simply means that the parameter `a` and the entry `arguments` are both linked with one another. If we change one, the other is changed automatically.

Let's try to go the other way round — change the entry `arguments` and then see whether the parameter gets updated:

``````function f(a) {
arguments = 'new';

console.log('arguments:', arguments);
console.log('a:', a);
}

f('old');``````
arguments: new
a: new

Yup, this works as well!

This confirms the fact that both the values are linked with one another — updating one automatically updates the other. We say that both the values are in sync with one another.

Note that, as stated before, each argument in `arguments` is linked with its corresponding parameter. This means that if a function, that requires an argument, is called without one, no linking would be made between the parameter and the corresponding entry in `arguments`.

This is simply because there is no entry in `arguments` for which linked could be done.

Consider the code below:

``````function f(a, b) {
b = 'new';
console.log('b', b);
console.log('arguments:', arguments);
}

f('old');``````

Here, `f()` has two parameters `a` and `b`, but when we call it in line 7, we just pass in one argument, which obviously goes into the parameter `a`. The parameter `b` is simply omitted.

The `arguments` object of `f()` has one entry in it, and that's linked with `a`. From this point onwards, there is no entry in `arguments` likewise no link exists for `b`.

Hence, even if we assign a value to `b` inside the function `f()`, the corresponding position in `arguments` would remain `undefined` (in fact, it won't even exist).

Linkages are only created one time, and that is while iterating over the `arguments` object. After that, no linkages can be made.

If we delete an element in `arguments` using the `delete` keyword for which a link exists, that link is severed in the deletion process. Now changing the respective parameter or creating the entry back in `arguments` won't change the other.

This can be seen in the code below:

Keep in mind, that the entire linkage behavior described here holds only for an exotic `arguments` object. This is the exotic feature it has to offer — parameters and entries in the object are connected to one another.

And restating it, exotic arguments objects are only created if the function is non-strict and doesn't use modern ES6-style parameters, such as rest, default-valued parameters etc. If these prerequisites aren't met, the argument object is termed as being 'ordinary'. Details follow in the next bit.

Read more about exotic arguments objects in the specification itself at https://262.ecma-international.org/12.0/#sec-arguments-exotic-objects.

#### Ordinary arguments object

Exotic `arguments` objects are — after all — quite exotic and flexible. They store values that are linked with corresponding parameters (if the parameters exist).

Now, if you think for a second, how useful is this feature? Or simply put, how often would you need this kind of linkage in your applications?

You change a parameter's value some other value. This would change `arguments` as well. But, if you'd be using the parameter in the function directly and not `arguments` (which would usually be the case), wouldn't this update to `arguments` be redundant?

Managing links to automatically update a parameter or an entry in `arguments` carries a bit of overhead with it. Some amount of time is definitely wasted in performing this exotic behavior.

Strict mode in JavaScript was created to enforce better programming practices and meaningful internal behavior. Thus, the idea of exotic arguments objects becomes useless when we have a strict function.

A function running in strict mode, or using modern ES6-style parameters, creates an `arguments` object referred to, by the ECMAScript spec, as an ordinary arguments object.

Let's see what's so ordinary about it.

With an ordinary `arguments` object, there is simply no concept of linkage between parameters and corresponding entries in `arguments`. Changing one won't change the other.

Yeah, well this looks like some ordinary behavior. But sometimes, actually most of the times, being ordinary is better than being exotic. Isn't it so?

Apart from this difference, it's also invalid to access the `callee` property of `arguments` when it is ordinary. We'll see more information regarding `callee` in the next section

## The `arguments.callee` property

Since the very first spec of ECMAScript, the `arguments` object of a function has a property `callee` on it which points to the function itself.

The purpose of `arguments.callee` was to be able to call an anonymous function recursively. Apart from it, there was no other way to do so, unless the anonymous function was assigned to some identifier.

Consider the code below:

``````var nums = [1, 2, 3, 4, 5, 6, 7];

var fibs = nums.map(function(n) {
if (n === 1) return 0;
if (n === 2) return 1;
return arguments.callee(n - 1) + arguments.callee(n - 2);
});

console.log(fibs);``````
[0, 1, 1, 2, 3, 5, 8]

Here we define an anonymous function as an argument to `map()` to calculate the Nth term in a Fibonacci sequence. The function calls itself recursively using `arguments.callee`.

Now, `arguments.callee` was useful only before the advent of named function expressions, when it was the sole way to invoke anonymous functions recursively. Even now, it may be useful in some very rare scenario, but largely it's recommended to avoid it, and use named function expressions instead.

`arguments.callee` reduces the readability of code, and is relatively slower as compared to calling a function via its name. Plus, with it it's not mandatory to name the function — naming functions is highly useful if we want to be able to debug errors easily, as names show in stack traces.

Note that it's only an exotic `arguments` object that allows the `callee` property to be accessed. If the object is not exotic, i.e. it's an ordinary `arguments` object, then accessing its `callee` property throws an error.

But why?

Recall that an `arguments` object is ordinary when it is in strict mode (or when it uses modern ES6-style parameters, but this is not useful for the moment), and as we know, strict mode aims to rectify many bad coding pratices in JavaScript which are otherwise allowed in sloppy mode (a fancy name for non-strict mode).

`arguments.callee` is one of these bad coding practices. It's long, kind of ugly in code, and slower than accessing the respective function via its name. Hence, it is disallowed in strict mode.

MDN has a nice section further detailing about strict mode and `arguments.callee`. You can read it at Strict mode - JavaScript | MDN — Making `eval` and `arguments` simpler.
It's also invalid to assign a value to `arguments.callee` in the case of an exotic `arguments` object.

## Rest parameters

ECMAScript 2015, also known as ES6, introduced tons and tons of elegant syntaxes and utilities intto the modern language to perform common operations more easily. One of them is rest parameters.

A rest parameter encapsulates all the remaining arguments after the arguments for all non-rest parameters in the form of an array.

It's denoted by preceding the name of the parameter with ellipsis (`...`). So if the name for the rest parameter is `param`, it would be denoted as `...param`.

There can be only one rest parameter in a function, and it ought to be the last parameter. With these two prerequisites met, the parameter works as follows:

When a function is invoked that has a rest parameter in it, each of the parameters preceding the rest parameter is resolved down with its respective argument. That is, the first argument goes into the first parameter, the second one goes into the second parameter and so on.

When all the preceding parameters are resolved, the rest of the arguments are encapsulated in a fresh array and this assigned to the rest parameter.

Did you notice the use of the word 'rest' above? That is where the name 'rest parameter' comes from — it contains the rest of the arguments.

Let's consider an example:

Say we have a function `showStudentInfo()` that takes in the name of a student and then a list of marks obtained by him/her in recent exams, in the form of mutiple arguments.

The list of marks can be variable as each student takes a variable number of subjects. Hence, to encapsulate all these arguments, the function makes the second parameter a rest parameter.

Here's the code of the function:

``````function showStudentInfo(name, ...marksList) {
console.log('Student name:', name);
console.log('Marks obtained:', marksList.join(', '));
console.log('-----'); // a divider line
}

showStudentInfo('Alice', 67, 80, 80, 91);
showStudentInfo('Bob', 85, 90, 95);``````
Student name: Alice
Marks obtained: 67, 80, 80, 91
-----
Student name: Bob
Marks obtained: 85, 90, 95
-----

Note that the function above could've been implemented using `arguments` as well, but not without processing the object first i.e converting it into an array, then slicing it from index `1` upto its end, and then calling the `join()` method on this slice. Too much work, isn't it?

With a rest parameter, we don't have to worry about any of these since all the arguments denoting the marks of the students are nicely laid out in an actual array.

Anyways, let's consider another example:

Below we have a function `showLangInfo()` that displays information about a programming language:

``````function showLangInfo(name, yearReleased, ...influencingLangs) {
console.log(name + ' was first released in ' + yearReleased + '.');
console.log('It was influenced by:');
console.log(' - ' + influencingLangs.join('\n - '));
}``````

The first parameter holds the name of the programming language, the second holds the year in which it was first released, and the last one, which is a rest parameter, holds a list of some languages that were influenced by this language.

Let's call the function:

``````function showLangInfo(name, yearReleased, ...influencingLangs) {
console.log(name + ' was first released in ' + yearReleased + '.');
console.log('It was influenced by:');
console.log(' - ' + influencingLangs.join('\n - '));
}

showLangInfo('JavaScript', 1995, 'Python', 'Java', 'Scheme');``````
JavaScript was first released in 1995.
It was influenced by:
- Python
- Java
- Scheme

If the languages influencing a programming language are not known, `showLangInfo()` can be called with just two args — `influencingLangs` would resolve to an empty array in this case.

``showLangInfo('ABC', 1987);``
ABC was first released in 1987.
It was influenced by:
-

Moving on, in both the examples above, there was at least one parameter preceding the rest parameter. This is not required at all. A function could have only one parameter and that being a rest parameter.

Let's create a function `sum()` that takes in an arbitrary number of arguments and adds them all together. The addition is accomplished using a `for` loops:

Once again, note that this function could've been made to use `arguments` instead of a rest parameter. And in this case, of summing all the args, `arguments` would have performed quite the same way.

#### No support on old browsers!

While using rest parameters in your code, keep in mind that they are part of ES6, and hence aren't supported on old browsers such as IE8 and before.

If you want your program to work consistently on these browsers, consider shifting to `arguments` or some other way to accomplish things in your program. If you don't want to change the code, another possible option is to use a transpiling tool that converts modern JavaScript into old JavaScript that's well supported on all old browsers.

Some popular transpiling choices are BabelJS and Traceur.

As stated before, specifying more than one rest parameter inside a function, or specifying the rest parameter before some other parameter leads to an error:

The following code snippets illustrates this:

``````// invalid to have more than one rest param
function f(...rest1, ...rest2) {
console.log(rest1, rest2);
}``````
``````// the rest param must be the last param
function f(...rest1, a) {
console.log(rest1, a);
}``````
Uncaught SyntaxError: Rest parameter must be last formal parameter

Both the snippets above log the same error, even though in the first one, the rest parameter is indeed the last parameter.

Well, if we see it carefully, the first snippet has a rest parameter before the last parameter. This will always be the case, when more than one rest parameter is specified — the first one would always be before some other parameter.

Hence, the JavaScript engine simplifies its work and just checks for when the rest parameter is not the last one in the list of parameters and logs an error if it isn't.

Compiler designers sure have to think cleverly.

ES6 provides an operator that works opposite to how the rest param works. It's called the spread operator.

It's idea is pretty apparent in its name. Let's see it...

The spread operator converts an iterable sequence into a list of arguments.

It's denoted as `...iterable`, where `iterable` is the iterable sequence to spread into a list of arguments.

``...iterable``

OK, but what exactly is an 'iterable sequence'?

An iterable sequence simply refers to any object that can be iterated over. Examples of iterable sequences that we've seen so far in this course are strings, arrays, and `arguments`.

As we shall see in the subsequent segment of this course, there are numerous iterable sequences frequently used in JavaScript such as `HTMLCollection`, `NodeList`, `DOMTokenList`, `HTMLOptionsCollection` and so on.

The spread operator can convert any of these into a list of arguments. Let's consider the operator as working on arrays.

Recall from the chapter JavaScript `Math` object, the method `Math.min()` takes an arbitrary number of args and returns the minimum value amongst them.

Now, more often than not, it's the case that the numbers are available as part of an array. The problem is that passing an array is useless to `Math.min()` — it finds the min value in the list of arguments, not in any one argument.

Consider the following:

``````var nums = [1, 50, 9, -4, -50, 0, 0, 10, 15, 13];
var min = Math.min(nums);

console.log('The minimum number is:', min);``````
The minimum number is: NaN

The minimum value output here is `NaN` although there is no such value in the array. This is because the `Math.min()` method never goes inside the array — it converts each of its arguments into a number and then throws out the minimum value amongst them.

And we already know from the JavaScript Arrays — Basics chapter that an array with more than one element always gets converted into `NaN`.

So, this means that `Math.min()` can't operate on an array.

Any other solutions for this problem of finding the minimum number in an array?

Well, you guessed it. We convert the array into a list of arguments using the spread operator.

Shown below is an illustration:

``````var nums = [1, 50, 9, -4, -50, 0, 0, 10, 15, 13];
var min = Math.min(...nums);

console.log('The minimum number is:', min);``````
The minimum number is: -50

All the magic lies in the expression `...nums`. What it does is simply converts the array into a list of arguments, which the `Math.min()` method could then easily process.

Easy?

## Default-valued parameters

Prior to ES6, there was no concept of default-valued parameters in JavaScript. While calling a function, if an argument was omitted, its corresponding parameter would simply be set to `undefined`.

Consequently, developers usually had to setup some boilerplate code to use a default value in this case, as shown below:

``````function f(a, b) {
b = (b === undefined) ? 'default' : b;
console.log(a, b);
}

// second argument provided
f(100, 200);

// second argument omitted
f(100);``````
100 200
100 default

This works. But after ES6, there's a much simpler syntax to achieve this. It's called a default-valued parameter.

It's denoted as follows:

``````function function_name(param1, param2 = defaultValue, param3, ...) {
// code
}``````

The parameter is denoted by putting an assignment syntax, i.e. an equals sign (`=`) followed by a value, after the parameter's name in the function definition.

Note that the `defaultValue` expression is computed each time the function is invoked.

Python also supports the idea of default-valued parameters, however the default values are computed only once when compiling the function.

This means that we could dynamically compute the default value using a function. We'll show such an example below.

Let's consider an extremely simple example.

Following we define a greeting function which takes in an argument, concatenates it with the text 'Hello' and finally outputs the result. When the function is called without an argument, the parameter is defaulted to 'World!'.

``````function greeting(txt = 'World!') {
console.log('Hello ' + txt);
}

greeting('JavaScript');
greeting();``````
Hello JavaScript
Hello World!

Not really difficult, was it?

Let's consider one more example.

Below we define a function `createMatrix()` that takes in the dimensions of a matrix and returns the respective 2D array back with all elements initialised to `0`:

``````function createMatrix(rows, cols = rows) {
return new Array(rows).fill(0).map(function(e) {
return new Array(cols).fill(0);
});
}

console.log(createMatrix(3));``````

The number of rows are provided in the first `row` argument while the number of columns are provided in the secone one. In case if the number of columns are omitted, a square matrix is created i.e. with the same number of rows and columns.

Note that in the code above, the parameter `cols` has access to the value of the parameter `rows`, defined before it. We'll see how is this possible internally in the section below.

In pratical code, this `createMatrix()` function could be useful.

Why not consider another example?

In the code below, we create a generic function `f()` that takes in three arguments and outputs them back as is. If the third argument is not provided, it's taken to be the value of the first argument multiplied by `5`:

``````function f(a, b, c = a * 5) {
console.log(a, b, c);
}

f(100, 200, 300);
f(100, 200);``````
100 200 300
100 200 500

Alright, as stated before, it's time to see how is a default-valued parameter able to access any of the preceding parameters.

#### Default-valued parameters accessing preceding parameters

Recall that parameters are simply local variables created when a function is called.

At a function's invocation, the whole list of arguments passed in is consolidated into an `arguments` object, then it's determined whether or not this object would be exotic or ordinary. In the case of a function having a default-valued parameter, `arguments` is ordinary.

Next, each parameter is created as a local variable, and assigned the corresponding argument, exactly in the order it appears in the function's header. For instance, in the case above, first a variable `a` is created and initialised to the argument `10`, then a variable `b` is created and initialised to the argument `20`.

When assigning to a parameter, if it's a default-valued parameter, then its argument is checked for being `undefined`. If it is `undefined`, the default value of the parameter is instead computed and assigned to the parameter.

At this point, all the preceding parameters are already created as local variables in memory with the corresponding arguments stored inside them. Likewise, the default-valued parameter can refer to them easily.

Internally, the function `f()` above could be thought of as working like the following:

``````function f() {
var a = arguments,
b = arguments,
c = (arguments === undefined) ? a * 5 : arguments;

console.log(a, b, c);
}

f(100, 200, 300);
f(100, 200);``````
100 200 300
100 200 500

This roughly depicts how are parameters implemented internally in JavaScript, although the internals don't obviously rely on these statements. In fact, the internals are what define these statements as well!