美文网首页
diff.js - 两个对象对比差异

diff.js - 两个对象对比差异

作者: TedFan | 来源:发表于2023-02-27 09:03 被阅读0次

    公司项目中有一个需求,要求对比两次填写表单时的差异,表单内容有对象,有数组,因此写了个diff.js,直接贴代码

    /**

     * 找到两个相同结构的对象的差异内容,并返回包含所有差异的数组

     * 注意对象内的值只能是简单类型,复杂类型不考虑

     * @param origin 原对象

     * @param current 可能修改过的对象

     * @param arrayKey 数组中需要对比的主键

     */

    export function diff(origin, current, arrayKey) {

      let diff = {}

      let log

      for (var key in origin) {

        if (typeof origin[key] === 'object' && typeof current[key] && origin[key] && current[key]) {

          if (origin[key] instanceof Array && current[key] instanceof Array) {

            log = diffArray(origin[key], current[key], arrayKey)

          } else {

            log = diffObject(origin[key], current[key])

          }

          if (Object.keys(log).length > 0) {

            diff[key] = log

          }

        } else if (origin[key] !== current[key]) {

          diff[key] = {

            origin: origin[key],

            current: current[key]

          }

        }

      }

      if (JSON.stringify(diff) == '{}') {

        return null

      } else {

        return diff

      }

    }

    /**

     * 找到两个相同结构的对象的差异内容,并返回包含所有差异的数组

     * 注意对象内的值只能是简单类型,复杂类型不考虑

     * @param originObj 原对象

     * @param currentObj 可能修改过的对象

     * @returns {{}} 包含所有差异的数组

     */

    function diffObject(originObj, currentObj) {

      const resultObj = {};

      // 遍历originObj的键数组,因为originObj和currentObj结构相同,所以不考虑结构上的差异

      Object.keys(originObj).forEach(key => {

        if (originObj[key] !== currentObj[key]) {

          // 将变化过的属性挂载到返回对象中

          resultObj[key] = {

            origin: originObj[key],

            current: currentObj[key]

          }

          // resultObj[key] = currentObj[key];

        }

      });

      if (JSON.stringify(resultObj) == '{}') {

        return false

      } else {

        return resultObj

      }

    }

    /**

     * 找到两个对象数组的差异,并打印从originList到currentList的所有变化

     * 注意约定id不能修改

     * @param originList 原数组

     * @param currentList 可能修改过的数组

     * @param keyName 子元素主键

     */

    function diffArray(originList, currentList, keyName) {

      let logArr = []

      let originListIds = originList.map(v => v[keyName])

      let currentListIds = currentList.map(v => v[keyName])

      originList.forEach((originObj) => {

        let index = currentListIds.indexOf(originObj[keyName])

        if (index >= 0) {

          let tempLog = diffObject(originList[index], currentList[index])

          // 原对象主键在现对象主键中

          if (tempLog) {

            // 如果templog有值,表示修改更新

            let log = {

              id: originObj[keyName],

              operate: 'modify',

              log: tempLog

            }

            logArr.push(log)

          }

        } else {

          // 原对象主键不在现对象主键中,表示原对象已被删除

          let log = {

            id: originObj[keyName],

            operate: 'delete',

            log: originObj

          }

          logArr.push(log)

        }

      })

      currentList.forEach((currentObj) => {

        // 查询新列表中的子元素主键是否存在于旧列表之中

        let index = originListIds.indexOf(currentObj[keyName])

        // 不存在则为新增

        if (index < 0) {

          let log = {

            id: currentObj[keyName],

            operate: 'add',

            log: currentObj

          }

          logArr.push(log)

        }

      })

      return logArr

    }

    用法

    let orgin = { a: '1', b: '2', c: { temp1: 'aaa', temp2: 'bbb' }, d: [{ id: '111', text: 'asd' }, { id: '222', text: 'asdsa' }] }

    let current = { a: '1', b: '45', c: { temp1: 'aaa', temp3: 'ccc' }, d: [{ id: '111', text: 'asd' }, { id: '333', text: 'xswedc' }] }

    console.log(diff(orgin, current, 'id'))

    相关文章

      网友评论

          本文标题:diff.js - 两个对象对比差异

          本文链接:https://www.haomeiwen.com/subject/cfzcldtx.html