質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

422閲覧

JSにおけるオブジェクト内容のマージ方法

退会済みユーザー

退会済みユーザー

総合スコア0

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

1グッド

2クリップ

投稿2018/05/31 07:43

編集2018/05/31 07:44

前提・実現したいこと

マップ的に利用するオブジェクトがネストされているようなオブジェクトが2つあり、そのマージ方法について、再帰的で汎用的な方法があるかお聞きしたいです。(言葉での説明だと分からないかと思うので、内容については「該当のソースコード」をご確認ください)
方法は非破壊的であるとよりうれしいですが、破壊的であっても良いです。
外部ライブラリも、可能な限り利用したくないです。

該当のソースコード

以下のmargeMagic()の実装方法で悩んでいます。

javascript

1function margeMagic(a, b) { 2 // 今回の質問点 3} 4 5const data1 = { a: 10, b: 11, c: { ca: "test", cb: 5, cd: ["hoge", "hogehoge"] } }; 6const data2 = { a: 11, c: { cc: "yes", cd: ["foo", "bar"] }, d: 10 }; 7const merged = margeMagic(data1, data2); 8console.log(c) // 期待 ⇒ { a: 11, b: 11, c: {ca: "test", cb: 4, cc: "yes", cd: ["foo", "bar"] }, d: 10}
  • data1 にしかキーがないプロパティはdata1 の値
  • data2 にしかキーがないプロパティはdata2 の値
  • 双方にキーがあるプロパティは
    -- 値がマップだったらそのマップ内も上記と同様の処理
    -- プリミティブや配列等であればdata2 の値(配列はマージせずそのまま)

試したこと

1. Object.assign

Object.assignでは、上記の例のmerged.cdata2.cの値になってしまいます。期待としては、merged.cもうまくマージされてほしい。(c: {ca: "test", cb: 4, cc: "yes", cd: ["foo", "bar"] }

2. for...inを利用

この場合、プロパティの中がさらにマップであれば同じことを繰り返すようにしたいのですが、ArrayやらFloat32Arrayやらはいちいち回したくないので普通に上書きしたい気持ちがあります。
そのため、「キーがあるかどうか」だけでは判別できません。
また、typeof hoge === "object"の場合にキーを見に行く、とやろうとするとhoge = new Array(100)の場合も分岐に入ってしまい回ってしまいます。
hoge instanceof Objectの場合にキーを見に行くと、ボクシングしたプリミティブ(new String("hoge")とか。非推奨っぽくはありますが)も通ってしまい、期待通りになりません。

結局今は

特定のオリジナル型に特化したマージ関数を作っているのですが、カッコ悪いしレイアウト変わったり他にも似たようなことやるとなるとかなり面倒なことになるので、汎用的なものを作りたいのです。

set0gut1👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

自力で作るのであれば、for-inを利用する、あるいはObject.keysなどで再帰的に回す他ないと思います。

ピュアなオブジェクト以外をマージするとカオスになりそうですので、自分が少し前の質問で答えたように、Object.getPrototypeOfの値をObject.prototypeと比較する、という形で絞るのがいいかなと思います。

投稿2018/05/31 08:06

maisumakun

総合スコア145123

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/05/31 08:19

なるほど、ピュアオブジェクトをマップとして使うと規定したうえで、`Object.getPrototypeOf(a) !== Object.prototype`の場合は上書いて、elseの時は再帰処理とやれば行けそうですね。 ありがとうございます。ちょっと試してきて結果を書きます。
退会済みユーザー

退会済みユーザー

2018/05/31 09:18

for...inを利用し、判定文にObject.getPrototypeOf(a) !== Object.prototypeを利用することで実現できました! ありがとうございました! #具体的なコードについては表現の範囲になるため、ここでは記載を避けます。申し訳ありません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問