Skip to content

Commit

Permalink
Reorganize arguments docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Josh-Cena committed Sep 3, 2022
1 parent 5818226 commit cecca2f
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ browser-compat: javascript.functions.arguments.@@iterator
---
{{jsSidebar("Functions")}}

The initial value of the **`@@iterator`** property is the same
function object as the initial value of the {{jsxref("Array.prototype.values")}}
property.
The **`@@iterator`** method of the [`arguments`](/en-US/docs/Web/JavaScript/Reference/Functions/arguments) object implements the [iterable protocol](/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) and allows `arguments` to be consumed by most syntaxes expecting iterables, such as the [spread syntax](/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) and [`for...of`](/en-US/docs/Web/JavaScript/Reference/Statements/for...of) loops.

The initial value of this property is the same function object as the initial value of the {{jsxref("Array.prototype.values")}} property (and also the same as [`Array.prototype[@@iterator]`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/@@iterator)).

{{js_property_attributes(1, 0, 1)}}

## Syntax

Expand Down
154 changes: 65 additions & 89 deletions files/en-us/web/javascript/reference/functions/arguments/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ browser-compat: javascript.functions.arguments

## Description

> **Note:** If you're writing ES6 compatible code, then [rest parameters](/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters) should be preferred.
> **Note:** "Array-like" means that `arguments` has a {{jsxref("Functions/arguments/length", "length")}} property and properties indexed from zero, but it doesn't have {{JSxRef("Array")}}'s built-in methods like {{jsxref("Array.forEach", "forEach()")}} or {{jsxref("Array.map", "map()")}}. See [§Description](#description) for details.
> **Note:** In modern code, [rest parameters](/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters) should be preferred.
The `arguments` object is a local variable available within all non-[arrow](/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) functions. You can refer to a function's arguments inside that function by using its `arguments` object. It has entries for each argument the function was called with, with the first entry's index at `0`.

Expand All @@ -31,62 +29,93 @@ arguments[1] // second argument
arguments[2] // third argument
```

Each argument can also be set or reassigned:
The `arguments` object is useful for functions called with more arguments than they are formally declared to accept, called [_variadic functions_](https://en.wikipedia.org/wiki/Variadic_function), such as {{jsxref("Math.min()")}}. This example function accepts any number of string arguments and returns the longest one:

```js
arguments[1] = 'new value';
function longestString() {
let longest = '';
for (let i = 0; i < arguments.length; i++) {
if (arguments[i].length > longest.length) {
longest = arguments[i];
}
}
return longest;
}
```

The `arguments` object is not an {{jsxref("Array")}}. It is similar, but lacks all `Array` properties except {{jsxref("Array.length", "length")}}. For example, it does not have the {{jsxref("Array.pop", "pop()")}} method.
You can use {{jsxref("Functions/arguments/length", "arguments.length")}} to count how many arguments the function was called with. If you instead want to count how many parameters a function is declared to accept, inspect that function's {{jsxref("Function.length", "length")}} property.

### Assigning to indices

However, it can be converted to a real `Array`:
Each argument index can also be set or reassigned:

```js
const args = Array.prototype.slice.call(arguments);
arguments[1] = 'new value';
```

It can also be converted with using an array literal. This method is shorter than above but allocates an empty array.
Non-strict functions that only has simple parameters (that is, no rest, default, or restructured parameters) will sync the value of variables new values in the body of the function with the `arguments` object, and vice versa:

```js
const args2 = [].slice.call(arguments);
function func(a) {
arguments[0] = 99; // updating arguments[0] also updates a
console.log(a);
}
func(10); // 99

function func2(a) {
a = 99; // updating a also updates arguments[0]
console.log(arguments[0]);
}
func2(10); // 99
```

As you can do with any Array-like object, you can use {{jsxref("Array.from()")}} method or [spread syntax](/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) to convert `arguments` to a real Array:
Non-strict functions that _are_ passed [rest](/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters), [default](/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters), or [destructured](/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) parameters will not sync new values assigned to argument variables in the function body with the `arguments` object. Instead, the `arguments` object in non-strict functions with complex parameters will always reflect the values passed to the function when the function was called.

```js
const args = Array.from(arguments);
// or
const args = [...arguments];
```
function funcWithDefault(a = 55) {
arguments[0] = 99; // updating arguments[0] does not also update a
console.log(a);
}
funcWithDefault(10); // 10

The `arguments` object is useful for functions called with more arguments than they are formally declared to accept. This technique is useful for functions that can be passed a variable number of arguments, such as {{jsxref("Math.min()")}}. This example function accepts any number of string arguments and returns the longest one:
function funcWithDefault2(a = 55) {
a = 99; // updating a does not also update arguments[0]
console.log(arguments[0]);
}
funcWithDefault2(10); // 10

```js
function longestString() {
let longest = '';
for (let i = 0; i < arguments.length; i++) {
if (arguments[i].length > longest.length) {
longest = arguments[i];
}
}
return longest;
// An untracked default parameter
function funcWithDefault3(a = 55) {
console.log(arguments[0]);
console.log(arguments.length);
}
funcWithDefault3(); // undefined; 0
```

You can use {{jsxref("Functions/arguments/length", "arguments.length")}} to count how many arguments the function was called with. If you instead want to count how many parameters a function is declared to accept, inspect that function's {{jsxref("Function.length", "length")}} property.
This is the same behavior exhibited by all [strict-mode functions](/en-US/docs/Web/JavaScript/Reference/Strict_mode#making_eval_and_arguments_simpler), regardless of the type of variables they are passed. That is, assigning new values to variables in the body of the function never affects the `arguments` object, nor will assigning new values to the `arguments` indices affect the value of variables, even when the function only has simple parameters.

### Using typeof with arguments
> **Note:** You cannot write a `"use strict";` directive in the body of a function definition that accepts rest, default, or destructured parameters. Doing so will throw [a syntax error](/en-US/docs/Web/JavaScript/Reference/Errors/Strict_Non_Simple_Params).
The {{jsxref("Operators/typeof", "typeof")}} operator returns `'object'` when used with `arguments`
### arguments is an array-like object

`arguments` is an array-like object, which means that `arguments` has a {{jsxref("Functions/arguments/length", "length")}} property and properties indexed from zero, but it doesn't have {{JSxRef("Array")}}'s built-in methods like {{jsxref("Array.forEach", "forEach()")}} or {{jsxref("Array.map", "map()")}}. However, it can be converted to a real `Array`, using one of [`slice()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice), {{jsxref("Array.from()")}}, or [spread syntax](/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax).

```js
console.log(typeof arguments); // 'object'
const args = Array.prototype.slice.call(arguments);
// or
const args = Array.from(arguments);
// or
const args = [...arguments];
```

The type of individual arguments can be determined by indexing `arguments`:
For common use cases, using it as an array-like object is sufficient, since it both [is iterable](/en-US/docs/Web/JavaScript/Reference/Functions/arguments/@@iterator) and has `length` and number indices. For example, [`Function.prototype.apply()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply) accepts array-like objects.

```js
console.log(typeof arguments[0]); // returns the type of the first argument
function midpoint() {
return (Math.min.apply(null, arguments) + Math.max.apply(null, arguments)) / 2;
}

console.log(midpoint(3, 1, 4, 1, 5)); // 3
```

## Properties
Expand Down Expand Up @@ -148,71 +177,18 @@ const listHTML = list('u', 'One', 'Two', 'Three');
*/
```

### Rest, default, and destructured parameters

The `arguments` object can be used in conjunction with [rest](/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters), [default](/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters), and [destructured](/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) parameters.

```js
function foo(...args) {
return args;
}
foo(1, 2, 3); // [1, 2, 3]
```

While the presence of rest, default, or destructured parameters does not alter [the behavior of the `arguments` object in strict mode code](/en-US/docs/Web/JavaScript/Reference/Strict_mode#making_eval_and_arguments_simpler), there are subtle differences for non-strict code.

In strict-mode code, the `arguments` object behaves the same whether or not a function is passed rest, default, or destructured parameters. That is, assigning new values to variables in the body of the function will not affect the `arguments` object. Nor will assigning new variables to the `arguments` object affect the value of variables.

> **Note:** You cannot write a `"use strict";` directive in the body of a function definition that accepts rest, default, or destructured parameters. Doing so will throw [a syntax error](/en-US/docs/Web/JavaScript/Reference/Errors/Strict_Non_Simple_Params).
Non-strict functions that are passed only simple parameters (that is, not rest, default, or restructured parameters) will sync the value of variables new values in the body of the function with the `arguments` object, and vice versa:

```js
function func(a) {
arguments[0] = 99; // updating arguments[0] also updates a
console.log(a);
}
func(10); // 99
```

And also:

```js
function func(a) {
a = 99; // updating a also updates arguments[0]
console.log(arguments[0]);
}
func(10); // 99
```

Conversely, non-strict functions that **are** passed rest, default, or destructured parameters **will not** sync new values assigned to argument variables in the function body with the `arguments` object. Instead, the `arguments` object in non-strict functions with complex parameters **will always** reflect the values passed to the function when the function was called (this is the same behavior as exhibited by all strict-mode functions, regardless of the type of variables they are passed):

```js
function func(a = 55) {
arguments[0] = 99; // updating arguments[0] does not also update a
console.log(a);
}
func(10); // 10
```
### Using typeof with arguments

And also:
The {{jsxref("Operators/typeof", "typeof")}} operator returns `'object'` when used with `arguments`

```js
function func(a = 55) {
a = 99; // updating a does not also update arguments[0]
console.log(arguments[0]);
}
func(10); // 10
console.log(typeof arguments); // 'object'
```

And also:
The type of individual arguments can be determined by indexing `arguments`:

```js
// An untracked default parameter
function func(a = 55) {
console.log(arguments[0]);
}
func(); // undefined
console.log(typeof arguments[0]); // returns the type of the first argument
```

## Specifications
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,25 @@ browser-compat: javascript.functions.arguments.length

The **`arguments.length`** property contains the number of arguments passed to the function.

{{js_property_attributes(1, 0, 1)}}

## Description

The arguments.length property provides the number of arguments actually passed to a function. This can be more or less than the defined parameter's count (see {{jsxref("Function.length")}}).
The `arguments.length` property provides the number of arguments actually passed to a function. This can be more or less than the defined parameter's count (see {{jsxref("Function.length")}}). For example, for the function below:

```js
function func1(a, b, c) {
console.log(arguments.length);
}
```

`func1.length` returns `3`, because `func1` declares three formal parameters. However, `func1(1, 2, 3, 4, 5)` logs `5`, because `func1` was called with five arguments. Similarly, `func1(1)` logs `1`, because `func1` was called with one argument.

## Examples

### Using `arguments.length`
### Using arguments.length

In this example we define a function that can add two or more numbers together.
In this example, we define a function that can add two or more numbers together.

```js
function adder(base /*, num1, …, numN */) {
Expand All @@ -32,8 +42,6 @@ function adder(base /*, num1, …, numN */) {
}
```

> **Note:** Note the difference between {{jsxref("Function.length")}} and arguments.length
## Specifications

{{Specifications}}
Expand Down

0 comments on commit cecca2f

Please sign in to comment.