retlat's blog

Array.prototype.mapとshallow copy

Arrayのdeep copyはどう作るのかなと思ってArray.prototype.map()を触っていたら、パッと思ったのと挙動が違うのでメモ
環境はSafari 13.0.5

まずArray.prototype.map()はMDNには以下のように記載されている

map() メソッドは、与えられた関数を配列のすべての要素に対して呼び出し、その結果からなる新しい配列を生成します。

ということで雑にcallbackFnで引数をそのまま返してみる

const a = [{a: 'aaa'}];
const b = a.map(v => v);

b[0].a = 'bbb';

console.log(a, b);
// Array (1)
//   0 {a: "bbb"}
// Array (1)
//   0 {a: "bbb"}

あれ? 新しいArrayが生成されるのに変数aの値も変わってる?
いや、Arrayとしては新しく生成されたけど、要素単位ではobjectだからshallow copyされてる?
ということでプリミティブ値のArrayで実験

const a = ['aaa'];
const b = a.map(v => v);

b[0] = 'bbb';

console.log(a, b);
// Array (1)
//   0 "aaa"
// Array (1)
//   0 "bbb"

変数aの方には影響が出なかったので、やっぱり要素がobjectだとそこだけはshallow copyみたい
ということは型の混ざるArrayだと?

const a = ['aaa', {a: 'aaa'}];
const b = a.map(v => v);

b[0] = 'bbb';
b[1].a = 'ccc';

console.log(a, b);
// Array (2)
//   0 "aaa"
//   1 {a: "ccc"}
// Array (2)
//   0 "bbb"
//   1 {a: "ccc"}

思った通りに混ざった
代入の仕様そのままだけど思い込みで違和感たっぷり

Post: 2020-02-18 Update: 2021-04-03
Tags: ECMAScript