オブジェクトをコピーする方法

JavaScriptは、オブジェクトをコピーする時に気を付ける点があります。

本ページでは、オブジェクトをコピーする3つの方法を説明します。

参照渡し

オブジェクトは、以下でコピーできます。この方法は、参照渡しと呼ばれます。

【参照渡しの方法】
//オブジェクト作成
const x = {
  address: "Tokyo",
  birthday: 2001
};

//参照渡し
const y = x;

これで、y.addressの"Tokyo"などの値を取り出せます。

しかし、y.address = "Kyoto"と代入すると、x.addressの値まで"Kyoto"になってしまいます。これは、変数yに代入されたのは、プロパティの値ではなくオブジェクトを参照するための情報だからです。

参照渡しの説明

xもyも同じオブジェクトを参照しています。このため、yでプロパティの値を変えると、xの値も変わるという訳です。

シャローコピー

参照渡しでは、同じオブジェクトを参照してしまうため、新しくオブジェクトを作って値をコピーすることもできます。

【シャローコピーの方法】
//オブジェクト作成
const x = {
  address: "Tokyo",
  birthday: 2001
};

//シャローコピー
const y = Object.assign({}, x);

これは、シャローコピー(shallow copy:浅いコピー)と呼ばれる方法です。

Object.assignは、コピーして新しいオブジェクトを作るメソッドです。Object.assign(z, x)と記述すると、zとx両方のプロパティと値がyにコピーされます。また、z自体もyと同じになります。上記の例では、zではなく{}となっているため、単純にxがyにシャローコピーされます。

これで、y.address = "Kyoto"などと変更しても、x.addressの値は変わりません。

しかし、これはプロパティがオブジェクト(オブジェクトが多重)になっていると使えません。深い階層のオブジェクトは、参照渡しになってしまいます。

また、以下のようにObject.createでプロトタイプを指定してオブジェクトを作ったとします。

【Object.createで作ったオブジェクトのシャローコピー】
//オブジェクト作成
const japan = {
  country: "Japan",
}

//japanをプロトタイプにしてオブジェクト作成
const x = Object.create(japan);
x.address = "Tokyo";
x.birthday = 2001;

//シャローコピー
const y = Object.assign({}, x);

この場合、継承によってx.countryは"Japan"になりますが、y.countryは"undefined"(未定義)になります。yのプロトタイプは、デフォルトで存在するObject.prototypeになります。

ディープコピー

ディープコピー(deep copy)は、深いコピーです。以下のように使います。

【ディープコピーの方法】
//オブジェクト作成
const x = {
  yamada:{
    address: "Tokyo",
    birthday: 2001
  },
};

//ディープコピー
const y = JSON.parse(JSON.stringify(x));

xの中、入れ子でyamadaがオブジェクトになっています。

JSON.stringifyは、オブジェクトを元に以下の文字列を作ります。

{"yamada":{"address":"Tokyo","birthday":2001}}

これは、JSON(JavaScript Object Notation)と呼ばれるデータ形式です。JSONは、JavaScriptでしか扱えないデータをテキスト形式に変換することで、他のプログラム言語でも使えるようにします。

JSON.parseでは、JSONを元にオブジェクトを作成します。つまり、コピーではなくJSONを元に新規作成しているため、元のxには影響ありません。

この方法も、プロトタイプのコピーはできません。

最初のページオブジェクトの使い方