+-
关于判断数组里对象的属性值有没有改变的问题

假如数组里有n个对象,把这n个对象里对象的属性或属性值有改变的对象单独拎出来,除了把新旧数组遍历循环对比,请问还有其他效率更高更优雅的方法吗?

可以参考vue的思想,劫持对象,触发set方法时把该对象提出来。

const temp = [
  {
    name: 1,
    children: ['1-1', '1-2'],
  },
  {
    name: 2,
    children: ['2-1', '2-2'],
  },
  {
    name: 3,
    children: ['3-1', '3-2'],
  },
]

const useObjObserver = (obj) => {
  const effects = new Map()
  const baseState = new Map()
  const INTERNAL_PAERNT_KEY = '__PARENT'
  const INTERNAL_FIELD_NAME = '__FIELD'
  const collectFieldNameToRoot = (obj) => {
    let path = [obj[INTERNAL_FIELD_NAME]]

    let parent = obj[INTERNAL_PAERNT_KEY]
    while (parent && parent[INTERNAL_FIELD_NAME]) {
      path.push(parent[INTERNAL_FIELD_NAME])
      parent = parent[INTERNAL_PAERNT_KEY]
    }

    return path.reverse().join('.')
  }
  const handler = {
    get(target, key, receiver) {
      if (typeof target[key] === 'object' && target[key] !== null) {
        target[key][INTERNAL_PAERNT_KEY] = target
        target[key][INTERNAL_FIELD_NAME] = key

        return new Proxy(target[key], handler)
      }
      return Reflect.get(target, key, receiver)
    },
    set(obj, prop, value) {
      const path = collectFieldNameToRoot(obj)
      effects.set(path, value)
      if (!baseState.has(path)) {
        baseState.set(path, obj[prop])
      }
      obj[prop] = value
      return true
    },
  }
  const observedObj = new Proxy(obj, handler)

  const applyChange = () => {
    effects.clear()
    baseState.clear()
  }
  const findChange = () => {
    const ans = []
    for (const key of effects.keys()) {
      const base = baseState.get(key)
      const effect = effects.get(key)

      if (base !== effect) {
        ans.push(key)
      }
    }

    return ans
  }

  return { observedObj, findChange, applyChange }
}

const { observedObj, findChange, applyChange, revoke } = useObjObserver(temp)

observedObj[0].name = '3'
observedObj[1].children[0] = '1-3'

console.log(findChange()) //[ '0', '1.children' ]

//应用变更
applyChange()

console.log(findChange()) //[]

//重新赋值,但是前后的值没有变
observedObj[2].children[1] = '3-2'

console.log(findChange()) //[]

//前后的值改变
observedObj[2].children[1] = '3-3'

console.log(findChange()) //[ '2.children' ]