(JavaScript) 配列の変数をpushすると参照渡しになる

(JavaScript) 配列の変数をpushすると参照渡しになる

 

JavaScriptでは、配列を格納した変数を別の変数にpushした際「参照渡し」になる
この現象を知らず、配列をpushする実装で小一時間時間を費やしたので、学んだことをメモ。

 

配列の変数を別の変数に格納すると「参照渡し」になる

pushの話をする前に、大前提として、
JavaScriptでは、配列を格納した変数を別の変数に格納すると「参照渡し」になると言うことを覚えておこう。

覚えておきたいポイント

JavaScriptでは、配列を格納した変数を別の変数に格納すると「参照渡し」になる

 

配列を代入して参照渡しが起きることを確認してみる

・変数xに配列(1, 2, 3) を格納し、変数yにxを代入する。
・その後、代入されたyの変数の一部を変更する。
・最後にx, y両者の変数の配列を確認する。

//変数xに配列(1, 2, 3) を格納し、変数yにxを代入
var x = [1,2,3];
var y = x;
console.log(y); // [1,2,3]

//yの変数の一部を変更
y[0] = 4;

//x, y両者の変数の配列を確認
console.log(x); // [4,2,3]
console.log(y); // [4,2,3]

 

変数xの配列の中身(1, 2, 3)は変更していないはずなのに、変更したyと同じ配列の値に変更されてしまっている。これが「参照渡し」の挙動である。

参照渡しは名前の通り、値の”参照”を渡しているので、参照先と参照元で同じ配列を共有するような動きとなるのである。

つまり、xとy、どちらも参照している実態は同じものであるため、
yだけを変更したつもりが、xも変更されてしまっていたと言う現象である。

 

本題:pushで配列を追加しても参照渡しになる

pushメソッドを使用して配列の変数を追加した際も、参照渡しになるので注意が必要である。

 

pushメソッドとは

pushメソッドを使うと、配列の末尾に値を追加することができる。

var x = [1,2,3];
x.push(4)
console.log(x); // [1,2,3,4] //末尾に4が追加された

 

pushメソッドで配列を追加する

pushメソッドで末尾に配列の変数を追加する。
渡した後は、push先の変数は多次元配列になる。

var x = [];
x.push([1,2,3])
console.log(x); // [[1,2,3]] 多次元配列

ここで、例によって、
配列を変数yに格納して、pushメソッドで変数xに追加してみる。

var x = [];
var y = [1,2,3];
x.push(y)
console.log(x); // [[1,2,3]]

そして、変数xの値を変更し、変数x,y両者の配列を確認してみる。

x[0].push(4)
console.log(x) // [[1,2,3,4]];
console.log(y) // [1,2,3,4]

配列を代入した時同様、
pushで追加した場合も、片方の変数の変更で、両方の変更が確認できる。

 

pushでの参照渡しを避ける方法

pushの際に参照渡しを避けるには、concatメソッドを使用する

concatメソッドは引数に指定した配列と結合して、新しい配列を返すメソッドだ。
この時、引数が空であれば、新しい配列(空)を作成して結合する。

「空の配列をダミー的に使用して、参照を切った新しい配列を作成してpushする」と言う部分が肝だ。

先ほどの処理を例に、変数yをconcatメソッドを使って変数xにpushしてみる。

var x = [];
var y = [1,2,3];
x.push(y.concat()) // 参照が切られた新しい配列(y+空の配列)がpushされる

x[0].push(4)
console.log(x) // [[1,2,3,4]];
console.log(y) // [1,2,3] <- 影響されていない

 

変数yへの影響がないことが確認できただろう。

concatメソッドを使用したことにより、値自体は同じだが、全く別の参照先を持つ新しい配列をpushしているので、変数yへの影響を避けることができたのである。

 

pushで参照私を避ける方法まとめ

pushの際に参照渡しを避けるには、concatメソッドを使用する。

concatメソッドは引数に指定した配列と結合して、新しい配列を返すメソッド。引数が空であれば、新しい配列(空)を作成して結合する。

 

記事が気に入った方はシェアをお願いします!

コメントを残す

メールアドレスが公開されることはありません。