JavaScript の arguments[n] は対応した 仮引数と 参照変数(=エイリアス) に該当する

:::note warn
この記事は 初心者が見ると混乱する要因になるので
初心者が見る資料 としては不適切です。
この特殊な条件でしか発生しないので通常のコーディングでは考慮する必要は無いです。
特に引数と arguments を 両用するのはとてもお勧めできません。
eslint の [`prefer-rest-params`](https://eslint.org/docs/latest/rules/prefer-rest-params) を有効にすることをおすすめします。
:::

# arguments と引数

言語的に参照渡しの無い言語である javascript には 参照渡しでいうところの 参照………つまり オブジェクト参照ではなく、いわゆる 変数のエイリアスにあたる動作は存在しない………と思っていたが、よくよく思っていたら存在したのでメモする。

具体的には次の様なコード

```js
function func(arg1){
    console.log('step1: ', arg1 === arguments[0]);
    arg1 = {};
    console.log('step2: ', arg1 === arguments[0]);
    arguments[0] = {};
    console.log('step3: ', arg1 === arguments[0]);
}
console.log('test: ', {} === {});
func({});
```

この実行結果は
```text
test: false
step1: true
step2: true
step3: true
```

となるつまり、 第一引数 は `arguments[0]` の参照（エイリアス）と言えるのである。

上記の例がわかりにくいというのであれば次の様な表現でもいいと思います。

```js
function func(arg1){
    console.log('step1: %o (%o, %o)', arg1 === arguments[0], arg1, arguments[0]);
    arg1 = "step2";
    console.log('step2: %o (%o, %o)', arg1 === arguments[0], arg1, arguments[0]);
    arguments[0] = "step3";
    console.log('step3: %o (%o, %o)', arg1 === arguments[0], arg1, arguments[0]);
}
func("step1");
```

この実行結果は次の様になります。
```text
step1: true ('step1', 'step1')
step2: true ('step2', 'step2')
step3: true ('step3', 'step3')
```

# 仕様書では

この動作について仕様書 を読んだところ NOTE 2 として次の説明があった。

> NOTE2
> The [integer-indexed data properties](https://tc39.es/ecma262/#integer-index) of an [arguments exotic object](https://tc39.es/ecma262/#arguments-exotic-object) whose numeric name values are less than the number of formal parameters of the corresponding [function object](https://tc39.es/ecma262/#function-object) initially share their values with the corresponding argument bindings in the function's [execution context](https://tc39.es/ecma262/#sec-execution-contexts). This means that changing the property changes the corresponding value of the argument binding and vice-versa. This correspondence is broken if such a property is deleted and then redefined or if the property is changed into an [accessor property](https://tc39.es/ecma262/#sec-object-type). If the arguments object is an [ordinary object](https://tc39.es/ecma262/#ordinary-object), the values of its properties are simply a copy of the arguments passed to the function and there is no dynamic linkage between the property values and the formal parameter values.

[10.4.4 Arguments Exotic Objects - ECMAScript® 2025 Language Specification](https://tc39.es/ecma262/#sec-arguments-exotic-objects)

とあり、 パラメータ数 に一致する index の位置にあたるものに関しては共有するとあります。つまり arguments が主となり共有している様なので次の様な実験を行うことを考えます。

```js:test1
function func(arg1) {
    console.log('deletable: %o', delete arg1);
    console.log('step1: %o (%o, %o)', arg1 === arguments[0], arg1, arguments[0]);
    arg1 = "step2";
    console.log('step2: %o (%o, %o)', arg1 === arguments[0], arg1, arguments[0]);
    arguments[0] = "step3";
    console.log('step3: %o (%o, %o)', arg1 === arguments[0], arg1, arguments[0]);
}
func("step1");
```

```js:test2
function func(arg1) {
    console.log('deletable: %o', delete arguments[0]);
    console.log('step1: %o (%o, %o)', arg1 === arguments[0], arg1, arguments[0]);
    arg1 = "step2";
    console.log('step2: %o (%o, %o)', arg1 === arguments[0], arg1, arguments[0]);
    arguments[0] = "step3";
    console.log('step3: %o (%o, %o)', arg1 === arguments[0], arg1, arguments[0]);
}
func("step1");
```

するとそれぞれ次の様な実行結果となります。

```text:test1 output
deletable: false
step1: true ('step1', 'step1')
step2: true ('step2', 'step2')
step3: true ('step3', 'step3')
```

```text:test2 output
deletable: true
step1: false ('step1', undefined)
step1: false ('step2', undefined)
step1: false ('step2', 'step3')
```

つまり arguments[n] を削除すると 引数との参照を切ることができるのです。

以上。