JavaScriptオブジェクトで参照渡し防止にはObject.create()を使用する

参照渡しとは

変数に代入が行われる際に値をそのまま渡すのではなく、参照先を渡すような仕様。

実際にコードを見て実行したほうが理解しやすい。

JavaScript
const person = {
  name: 'Sato'
}
const me = person
me.name = 'Yamada'
 
console.log(person.name)
// => 'Yamada'
 
console.log(me.name)
// => 'Yamada'
 
console.log(person.name)
// => 'Yamada'

上記のコードのconsole.logの結果はすべて 'Yamada' になる。

const me = person という記述だとmeにpersonを代入する際に参照先を渡しているのでme.name = 'Yamada' にすると personのnameも 'Yamada' になる。

Object.create()を使用する

「javascript 変数 参照」などで検索すると解決策としてJSON.stringifyとJSON.parseを使用する方法の記事が多く表示される。

JavaScript
const me = JSON.parse(JSON.stringify(person))

ただし、これだとコードの可読性が悪いし、処理も2回無駄に実行されて処理が遅いのでよろしくない。

この書き方はIE8も対象にしていたころの古い書き方なので現代であればObject.create()を使用したほうが良いだろう。

JavaScript
const person = {
  name: 'Sato'
}
const me = Object.create(person)
me.name = 'Yamada'
 
console.log(person.name)
// => 'Sato'
 
console.log(me.name)
// => 'Yamada'
 
console.log(person.name)
// => 'Sato'

Object.create() - JavaScript | MDN

ディープコピーならstructuredCloneを使用する

Object.create() は指定したオブジェクトをプロトタイプとして持つ新しいオブジェクトを作成するメソッドなので、ディープコピーをしたいのであればstructuredCloneを使用するのが適切です。

JavaScript
const original = { greet: 'hello', info: { name: 'John' } }
const deepClone = structuredClone(original)
deepClone.info.name = 'Yamada'

console.log(original.info.name)  // 'John'
console.log(deepClone.info.name) // 'Yamada'

structuredClone() グローバル関数 - Web API | MDN