意外な所で非破壊処理(Array.prototype.concat)


JavaScriptでゴリゴリ配列を操作していましたが、破壊的か非破壊的かわかりづらいメソッドがあるなと感じました。

破壊的・非破壊的

まず、「破壊的」メソッドというのは元の配列を変更してしまうメソッドのことです、いちばんわかりやすい例としては.push().pop()があります。

逆に、「非破壊的」なメソッドは元の配列に変更をくわえず、別に結果を返すものです。.join().slice()などがあります。

あなたの予想に反して、元の配列は変更されていないでしょうか?

そして、Arrayには.concat()というメソッドがあります。「連結」ということで、元の配列につないでくれると考えるかもしれませんが、じつは…

concat は this や引数として与えられた配列を変更しませんが、その代わりに元の配列から結合させた同じ要素のコピーを含むシャローコピー (1 次元の配列要素までの浅いコピー) を返します。

MDNの解説より)

ということで、じつは非破壊のメソッドでした。ただ、もちろんこの事実が便利な時もちょくちょくあります(自分自身、積極的に使っていたりします)。

破壊的につなぎたい時

ただ、非破壊的ということは、長い配列を作ろうとすればこの前も取り上げたような事態となって、パフォーマンスは出ません。それでは、破壊的に配列を連結するにはどうすればいいのでしょうか。

ここで、.push()が破壊的だということを利用します。そして、引数をいくつでも取れるので、applyで連結すべき配列を引数にしてしまえば、問題は解決します。

//arrへarr2を破壊的に連結する
arr.push.apply(arr, arr2);