JavaScript でオブジェクトをコピーする
さまざまなプログラミング言語にはさまざまなデータ構造があり、データを整理してメモリに保存できます。各データ構造は一意に機能します。たとえば、C++ と Java には、データを Key-Value 形式で格納するための Hashmap があります。同様に、JavaScript には、オブジェクトと呼ばれるデータ構造があり、データをキー値
形式で保存できます。
オブジェクトは、データへのアクセスに役立ちます。キーを使用して、オブジェクト内の任意のデータに簡単にアクセスできます。この記事では、JavaScript でオブジェクトをコピーするさまざまな方法を紹介します。
JavaScript オブジェクトは変更可能であり、参照として保存されることに注意してください。すでにオブジェクトを作成していて、それを他のオブジェクトに割り当てたい場合、そのオブジェクトはこのオブジェクトのアドレスを保持します。オブジェクトの参照を別のオブジェクト内に格納しているため、この新しいオブジェクトを使用して、元のオブジェクト内に存在する値を簡単に変更できます。
var a = {'name': 'Adam', 'company': 'Google'}
var b = a;
b.name = 'Sam'
console.log(a.name, b.name);
出力:
Sam Sam
上記の例からわかるように、あるオブジェクトを別のオブジェクトに割り当てても、オブジェクト自体はコピーされません。古いオブジェクトのアドレスのみが新しいオブジェクトに格納されます。
JavaScript でオブジェクトをコピーする方法は 2つあります。1つの方法は浅いコピーと呼ばれ、別の方法は深いコピーと呼ばれます。これらの方法を実装するために、次のようにいくつかの JavaScript メソッドを利用できます。
JavaScript でオブジェクトを浅くコピーする
浅いコピーでは、オブジェクトの最初のレベルに存在する key-value
ペアのみが新しいオブジェクトにコピーされます。また、配列や内部の別のオブジェクトなど、ネストされたすべての要素またはプロパティはコピーされず、代わりに、それらの参照がこのオブジェクトに格納されます。
浅いコピーでは、元のオブジェクトの一部のプロパティも影響を受けます。これを理解するには、以下の例を参照してください。
var obj1 = {
'firstName': 'James',
'lastName': 'Bond',
'films': ['No Time To Die', 'Spectre', 'Skyfall', 'Quantum of Solace'],
'actors':
{'characters': {'realName': 'Daniel Craig', 'fakeName': 'James Bond'}}
}
この例では、obj1
というオブジェクトがあります。JavaScript を使用してこのオブジェクトを浅くコピーするには、Object.assign()
とスプレッド演算子 ...
を使用できます。JavaScript で以下のメソッドを使用して、obj1
でシャローコピーを実行してみましょう。
Object.assign()
メソッド
Object.assign()
メソッドは 2つのパラメーターを取ります。最初のパラメータは、コピーが完了した後に返される target
オブジェクトです。2 番目のパラメーターは、コピーするオブジェクト obj1
です。この例では、空のオブジェクト {}
をターゲットとして渡します。これは、obj1
内のすべての要素がこの空のオブジェクトにコピーされるためです。コピーが完了すると、Object.assign()
は、obj2
変数内に格納する新しいオブジェクトを返します。
var obj2 = Object.assign({}, obj1);
後で、このオブジェクトのプロパティを変更し、これがシャローコピーと呼ばれる理由を実際に確認します。
obj2.firstName = 'Camila';
obj2.films[0] = 'abcccc';
obj2.actors.characters.realName = 'Camila';
console.log(obj1);
console.log(obj2);
出力:
ここでは、obj2、firstName
、films[]
配列の最初のフィルム、および actors.characters
オブジェクトの realName
プロパティを使用して 3つの値を変更します。次に、両方のオブジェクトを出力します。
上の画像は、両方のオブジェクトで firstName
プロパティのみが変更されていないことを示しています。他の 2つのプロパティ、films[]
と realName
は両方のオブジェクトで変更されています。firstName
プロパティは一意であるため、これはシャローコピーと呼ばれますが、ここにアドレスを格納しているため、他のプロパティは両方のオブジェクトに共通です。ここでは、最初のレベルに存在するプロパティのみがコピーされます。
- スプレッド演算子(
...
)
残りの演算子は、obj1
のプロパティを obj2
にコピーします。これは、オブジェクトのプロパティを浅くコピーする Object.assign()
に似ています。スプレッド演算子を使用してオブジェクトをコピーするには、スプレッドシンボルの後にオブジェクト名を書き込む必要があります。
var obj2 = {...obj1};
obj2.firstName = 'Camila';
obj2.films[0] = 'abcccc';
obj2.actors.characters.realName = 'Camila';
また、Object.assign()
メソッドを使用した後に得られたものと同じ出力が得られます。
JavaScript でオブジェクトをディープコピーする
ディープコピーでは、すべての key-value
ペアが新しいオブジェクトにコピーされます。ディープコピーを実行するには、JSON.parse()
メソッドと JSON.stringify()
メソッドを使用できます。ディープコピーは、プロトタイプオブジェクト内に存在するプロパティをコピーしないことに注意してください。
JSON.stringify()
を使用して、最初にオブジェクト全体(この場合は obj1
)を文字列に変換し、その後、JSON.parse()
メソッドを使用して解析します。この文字列を JSON 形式に戻します。
let obj2 = JSON.parse(JSON.stringify(obj1));
ここでは、obj1
内のプロパティに影響を与えない obj2
内の任意のプロパティを変更できます。
obj2.firstName = 'Camila';
obj2.films[0] = 'abcccc';
obj2.actors.characters.realName = 'Camila';
出力:
以前に変更したのと同じ値を変更していますが、obj2
のプロパティを変更しても、obj1
のプロパティには影響がないことがわかります。
Sahil is a full-stack developer who loves to build software. He likes to share his knowledge by writing technical articles and helping clients by working with them as freelance software engineer and technical writer on Upwork.
LinkedIn