Фиксирование изменений словаря для применения их к другому

Есть объект A, он содержит произвольный многоуровневый словарь B, при изменении любого элемента в котором должны производиться такие же изменения в идентичном словаре C.
Объект A и словарь в нём можно оформить как угодно, словарь С и словарь B не должны иметь ссылки на одинаковые объекты.
Словари сходятся к примитивным типам (число, строка и т.д.).
Желательно чтоб словарь B вёл себя как обычный словарь.


Ответы (1 шт):

Автор решения: NanzeRT

Увидев в одном из примеров кода, как можно использовать рекурсию с Proxy, написал свой велосипед:

var reqQuerry = []

let memHandler = {
  get (target, key) {
    reqQuerry.push(key)
    if (typeof target[key] === 'object' && target[key] !== null) {
      return new Proxy(target[key], memHandler)
    } else {
      return target[key];
    }
  },
  set (target, key, value) {
    if (target[key] !== value) {
      console.log('setting Memory');
      target[key] = value
      let Mem = Memory
      for (let i = 0; i < reqQuerry.length; i++) {
        Mem = Mem[reqQuerry[i]]
      }
      Mem[key] = value
    }
    return true
  },
  deleteProperty (target, key) {
    if (key in target) {
      delete target[key]
      let Mem = Memory
      for (let i = 0; i < reqQuerry.length; i++) {
        Mem = Mem[reqQuerry[i]]
      }
      delete Mem[key]
      return true
    }
    console.log('property not found at Memory.' + reqQuerry.join('.') + '.' + key + '!');
    return false
  }
}

var _memory = new Proxy({_mem : null}, {
  update (target) {
    if (target._mem == null) {
      console.log('refreshing Memory');
      target._mem = Object.assign({}, Memory)
    }
    reqQuerry = []
  },
  get (target, key) {
    this.update(target)
    return memHandler.get(target._mem, key)
  },
  set (target, key, value) {
    this.update(target)
    return memHandler.set(target._mem, key, value)
  },
  deleteProperty (target, key) {
    this.update(target)
    return memHandler.deleteProperty(target._mem, key)
  }
})

module.exports = _memory;

Писал скрипт для игры Screeps, так что синтаксис соответствующий.
A => _memory B => _mem C => Memory

→ Ссылка