【JavaScript】配列を引数渡しすると破壊的に動作する話【メモ書き】

# はじめに
こちらの記事は、これ（"はじめに"）を追記している現在、`5200 views`を超えており、
たくさんの方に見ていただけていること、感謝致します。

本記事では、コメントでいただいたことを元にある程度の表現・言い回しの修正をしておりますが、
あくまで私がJavaScriptを使っていて思ったとおりに動作しなかったという事実から、
本記事を書いた当時、自力で調べた知識で構成されており、
JavaScriptの仕様を**完全に理解しているわけではありません**。
そのため、この記事では**当時の私がやりたかったことを実現する方法**が述べられており、
それ以外については、**<font color="Red">その限りではありません</font>**。

<font color="Red">詳細な仕様等の確認は、本記事ではなく、
***本記事コメント欄***や***[JavaScriptに参照渡し/値渡しなど存在しない - Qiita](https://qiita.com/yuta0801/items/f8690a6e129c594de5fb "JavaScriptに参照渡し/値渡しなど存在しない - Qiita")***などを参照していただくことを***強く***推奨します。</font>
本記事がJavaScriptのさらなる理解への道標になると幸いです。

特に、上記記事はこの修正をしているタイミングで読ませていただきましたが（~~遅い~~）、
本記事執筆当時は知らなかったことが詳細に書かれており、大変勉強になりました。
ありがとうございました。

<font color="Blue">JavaScriptって難しいですね。</font>
~~だけどその苦しみこそが楽しいと感じてしまうのは私だけでしょうか？~~
<font color="#fff">私はどうやら、少なくともプログラミングにおいてはドＭなようです。</font>
尚、今回の追記においては、以下の本編の内容は一切変更しておりません。
予めご了承ください。<font color="#fff">正直、ほぼほぼ書き直さなきゃならなくなるので面倒なのです。</font>

***

#　本編


この記事は、筆者が[配列をシャッフルするアルゴリズムを思いついたが既存だった話【JavaScript/Rubyサンプルコードあり】 - Qiita](https://qiita.com/yukuduri/items/f1e2f00bc9f28ebe5b35 "配列をシャッフルするアルゴリズムを思いついたが既存だった話【JavaScript/Rubyサンプルコードあり】 - Qiita")を書いていたときに気づいたメモです。


***


まず、このコードを見て欲しい。

```JavaScript
const swapAry1 = (ary) => {
  const newAry = [];
  const len = ary.length;
  for (let i = 0; i < len; i++){
    newAry.push(ary.pop());
  }

  return newAry;
} 

a = [1, 2, 3, 4, 5];
console.log('swapAry1');
console.log(a);
console.log(swapAry1(a));
console.log(a);
```
`swapAry1`は引数で渡された配列のすべての順番を逆にする関数だ。
`swapAry1`の実行時、`swapAry1`では`ary`が`pop()`により破壊されている。
が、これらを実行したとき、

```
swapAry1
[ 1, 2, 3, 4, 5 ]
[ 5, 4, 3, 2, 1 ]
[ 1, 2, 3, 4, 5 ]
```
となるだろうと、思うかもしれない。（つまり、引数で渡した配列`a`まで破壊されているとは思わないかもしれない。）

しかし、実際には

```
swapAry1
[ 1, 2, 3, 4, 5 ]
[ 5, 4, 3, 2, 1 ]
[]
```

となり、引数で渡した配列`a`まで破壊されている。

どうやら配列を引数にとったとき、~~「参照渡し」~~**（コメントでご指摘があった通り、『参照の値渡し』や『オブジェクト渡し』が正確な表現のようです。詳細はコメント欄にて。）**がされているらしく、仮引数の配列**の要素**を変更するとそれが実引数の配列にまで影響するようである。参照の値渡しと値渡しについては[JavaScriptで配列のコピー（値渡し） - Qiita](https://qiita.com/takahiro_itazuri/items/882d019f1d8215d1cb67)を参照してもらえれば、と。私のこの説明よりわかりやすいと思います。

ついでに、アロー関数以外でもそうなのか試してみました。

```JavaScript
const swapAry2 = function(ary){
  const newAry = [];
  const len = ary.length;
  for (let i = 0; i < len; i++){
    newAry.push(ary.pop());
  }

  return newAry;
};

a = [1, 2, 3, 4, 5];
console.log('swapAry2');
console.log(a);
console.log(swapAry2(a));
console.log(a);

function swapAry3(ary){
  const newAry = [];
  const len = ary.length;
  for (let i = 0; i < len; i++){
    newAry.push(ary.pop());
  }

  return newAry;
};

a = [1, 2, 3, 4, 5];
console.log('swapAry3');
console.log(a);
console.log(swapAry3(a));
console.log(a);
```
実行結果は

```
swapAry2
[ 1, 2, 3, 4, 5 ]
[ 5, 4, 3, 2, 1 ]
[]
swapAry3
[ 1, 2, 3, 4, 5 ]
[ 5, 4, 3, 2, 1 ]
[]
```

となりました。**ダメです！**
破壊的なものが欲しいときにはこれでも問題ないですが。

これを防ぐには、このようにすると良いでしょう。

```JavaScript
const swapAry = (initAry) => {
  const ary = initAry.slice();
  const newAry = [];
  const len = ary.length;
  for (let i = 0; i < len; i++){
    newAry.push(ary.pop());
  }

  return newAry;
} 
a = [1, 2, 3, 4, 5];
console.log('swapAry');
console.log(a);
console.log(swapAry(a));
console.log(a);
```

実行結果

```
swapAry
[ 1, 2, 3, 4, 5 ]
[ 5, 4, 3, 2, 1 ]
[ 1, 2, 3, 4, 5 ]
```