Lodashの.extend()/.assign()と.merge()の違いを徹底解説!浅いコピーと再帰的マージの使い分け
JavaScriptでオブジェクトを扱う際、Lodashの_.assign()(または_.extend())と_.merge()はどちらもオブジェクトを結合するためのメソッドですが、その動作には重要な違いがあります。この記事では、両者の違いを具体例とともにわかりやすく解説します。
_.assign() / _.extend() の動作:浅いコピー(シャローコピー)
assignやextendは、ソースオブジェクトの各プロパティを取り出し、その値をそのままデスティネーション(コピー先)にコピーします。
ポイントは、プロパティの値がそれ自体オブジェクトだった場合でも、その中身を再帰的にたどらないという点です。つまり、ネストされた子オブジェクトごと丸ごと参照がコピーされます。この方式は「浅いコピー(シャローコピー/シャロークローン)」と呼ばれます。
結果として、デスティネーションに同名のプロパティがある場合、その値はソース側の値で完全に上書きされます。
_.merge() の動作:再帰的なディープマージ
一方、mergeは、ソースオブジェクトの各プロパティについて、「その値がオブジェクト自身かどうか」をチェックします。
もしオブジェクトであれば、再帰的に処理を進め、子オブジェクトのプロパティ同士をソースからデスティネーションへ対応付けて統合します。これにより、ネストされた構造を持つオブジェクトでも、階層を保ったまま内容をマージできます。この方式は「ディープマージ(深い結合)」と呼ばれます。
コード例
実際のコードで違いを見てみましょう。
let _ = require('lodash');
let destination = {
a: {
b: 1,
c: 2
},
};
let source = {
a: {
d: 2,
c: 3
},
};
console.log(_.merge(destination, source));
console.log(_.extend(destination, source));
出力結果
このコードを実行すると、以下の出力が得られます。
{ a: { b: 1, c: 3, d: 2 } }
{ a: { d: 2, c: 3 } }
結果のポイント
mergeでは、aの中のプロパティが再帰的に統合され、b・c・dすべてが保持されています(cはソース側の値3で上書き)。一方、extendでは、aの値がソース側のオブジェクトで丸ごと置き換えられているため、デスティネーション側にあったb: 1は失われています。
使い分けの目安
- _.assign() / _.extend():フラットなオブジェクトの結合や、単純にプロパティを上書きしたい場合に最適。処理も高速です。
- _.merge():設定オブジェクトのようなネストされたデータ構造を統合したい場合に最適。既存の階層構造を壊さずにマージできます。
ネストされたオブジェクトを扱う場合は、意図しないデータ損失を避けるために、mergeを使うのが安全です。
-
C#と.NETの違いをわかりやすく解説!言語とフレームワークの関係
C#と.NETの基本的な違いC#(シーシャープ)はマイクロソフトが開発したプログラミング言語であり、一方の.NET(ドットネット)はアプリケーション開発を支援するフレームワークです。この2つは密接な関係にありますが、それぞれの役割はまったく異なります。.NETの中核となる「共通言語ランタイム(CLR)」.NETには「共通言語ランタイム(CLR:Common Language Runtime)」と呼ばれる仮想的な実行環境が組み込まれています。CLRはメモリ管理、例外処理、セキュリティなどを担当し、.NET上で動作するすべてのアプリケーションの土台となる重要なコンポーネントです。C#だけじゃない!
-
GoとJavaの違いを徹底比較!特徴と使い分けのポイント
プログラミング言語を選ぶ際、「Go」と「Java」のどちらを採用すべきか迷う開発者は少なくありません。どちらもGoogleや企業システムで広く使われる人気言語ですが、設計思想や言語仕様には大きな違いがあります。本記事では、それぞれの言語の特徴を解説したうえで、両者の主な違いを比較表を使ってわかりやすく整理します。 GoとはGoはGoogleが開発した手続き型(プロシージャル)プログラミング言語です。プログラムはパッケージ単位で構成され、シンプルで読みやすいコード記述を重視した設計になっています。動的言語に近い柔軟なパターンを取り入れつつ、静的型付けによる安全性も兼ね備えています。また、軽量スレ