web-dev-qa-db-ja.com

JS再帰オブジェクト割り当て

Object.assign()を使用すると、最上位のオブジェクトのみが拡張されることを学びました。オブジェクトを深く拡張するにはどうすればよいですか?たとえば、次のソースオブジェクトがあるとします。

_const source = {
  id: 1,
  otherKey: {},
  params: {
    page: {
      a: 1,
      b: {}
    },
    data: {
      b: 1
    }
  }
}
_

そして、私は次のようにObject.assign()を使用しています。

_Object.assign({}, source, {
  params: {
    page: {
      a: 2
    }
  }
}
_

結果は次のようになります。

_{
      id: 1,
      otherKey: {},
      params: {
        page: {
          a: 2
        }
      }
}
_

浅いクローンの方法でparams.dataキーとparams.page.bキーを保持するにはどうすればよいですか。

_oldObject.params.data === newObject.params.data  // true
oldObject.params.page === newObject.params.page  // false
oldObject.params.page.b === newObject.params.page.b // true
_

注:この質問は 浅いマージの代わりに深いマージする方法 と同じではありません。そこでの答えは期待される結果を与えません。

これを確認してください bin 上記のリンクから回答が得られます。

6
undefined

したがって、投稿されたコードでは、ソースとターゲットの両方に同じキーが含まれている場合、何も起こりません。オブジェクトは子に再帰されます。ただし、単に内部ブロックをこれに変更すると、次のようになります。

if (!target[key]) { 
  Object.assign(target, { [key]: {} });
}else{          
  target[key] = Object.assign({}, target[key])
}
mergeDeep(target[key], source[key]);

これにより、ソースとターゲットの両方で見つかったすべてのキーに新しく割り当てられたオブジェクトが作成されます。ただし、興味深いことに、これを行うと、期待されるfalseysがコンソールに表示されません。これは、ターゲットが常に結果と一致するためです。これは、最終的に変更されたオブジェクトであるためです。したがって、期待されるfalseの結果を得るには、次のようなことを行う必要があります。

var tester = source.params
const result = mergeDeep(source, b)
console.log(tester === result.params) // this will be false after the above addition

ここで希望の結果を確認できます: http://jsbin.com/vicemiqiqu/1/edit?js,console

2
Matt Way