Object.assign() と Object.freeze()

Object.assign() は第1引数を書き換えて返します。後ろが勝つこと、複製が1段しか効かないこと、 getter が値に変わること、freeze() も1段しか凍らないことを実行して確かめます。

実行して検証済み処理系Node 22.22.3対応ES2015難易度●●○○○目安8更新

Object.assign() は、第1引数そのものを書き換えて、それを返します。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
{"a":9,"b":2} true {"a":9,"b":2}
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
{"a":1,"b":2} {"a":1} false

渡した target が変わっています。 ここが最大の注意点です。

  • 後ろに書いたものが勝ちます
  • 返るのは新しいオブジェクトではなく、第1引数そのもの

元を壊したくないなら先頭に空を置く

javascript
const base = { deep: { n: 1 } };
const copied = Object.assign({}, base);

copied.deep.n = 99;

console.log(base.deep.n);
99
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
1 99

{} を先頭に置くと、base は無傷です。 いまは { ...base, b: 2 } と書くほうが短く、意図も伝わります。 → スプレッド構文と残余

Object.assign() がいま必要なのは、「既にあるオブジェクトを書き換えたい」ときだけです。それ以外はスプレッドで足ります。

複製は1段しか効かない

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
{"a":1,"b":2}
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
TypeError: Cannot convert undefined or null to object

copied は別のオブジェクトですが、deep は同じものを指しています。 これを浅いコピーと呼びます。スプレッドでも同じです。

深く複製するなら structuredClone() です。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
{"own":2} 1 false false
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
{ value: 2, writable: true, enumerable: true, configurable: true }

nullundefined は無視される

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
{"a":1,"deep":{"n":1}}
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
TypeError: Cannot assign to read only property 'a' of object '#<Object>'

落ちません。 条件によって渡すものが消えても、そのまま通ります。

ただし第1引数が null なら落ちます。そこだけは対象になれません。

javascript
const frozen = Object.freeze({ deep: { n: 1 } });

frozen.deep.n = 99;

console.log(frozen.deep.n);
console.log(Object.isFrozen(frozen), Object.isFrozen(frozen.deep));
99 true false

TypeError: Cannot convert undefined or null to object

入るのは「自分の・列挙できる」ものだけ

  • 受け継いだものは入らない
  • 列挙できないものは入らない
  • Symbol の鍵は入るObject.keys() とはここだけ違う)

Object.keys() / values() / entries()

get は値に変わる

呼ばれた結果が、ただの値として入ります。 get のまま持っていきたいなら Object.defineProperties()Object.getOwnPropertyDescriptors() を使ってください。

Object.freeze() — 変えられなくする

書き換えも追加も黙って無視されます。

strict モードでは、無視ではなく落ちます。

import / export のあるファイルは自動的に strict なので、 実務では落ちるほうが普通です。

freeze も1段しか効かない

外側は凍っていますが、中の入れ子は凍っていません。 深く凍らせたいなら、自分で辿って凍らせる必要があります。

まとめ

  • Object.assign()第1引数を書き換えて、それを返す
  • 元を壊したくないなら {} を先頭に置く。ふだんはスプレッドで足りる
  • 後ろが勝つ。null / undefined は無視される
  • 複製も凍結も1段だけ。 深くしたいなら structuredClone() か自分で辿る
  • get呼ばれた結果の値になる
  • freeze() は strict では黙って無視ではなく落ちる

この記事の根拠

  1. Object.assign — ECMAScript® 2026 Language Specificationtc39.es
  2. Object.freeze — ECMAScript® 2026 Language Specificationtc39.es
  3. Object.assign() — MDNdeveloper.mozilla.org

掲載しているコード例は、公開前に読み手が押したときに動くのと同じもので実行して出力を突き合わせています。結果はリポジトリに残しています。

このページの原文(Markdown)