如何遍历JS对象和里面的所有数组和对象,与它的副本进行比较?

How to traverse JS object and all arrays and objects inside to compare it with its copy?

我在 Angular 中有一个 selectedItem 对象,它包含其他对象和数组。我使用 JSON 技巧创建深拷贝:

$scope.editableItem = JSON.parse(JSON.stringify($scope.selectedItem))

然后我在输入中使用editableItem模型,改变里面的一些值。 selectedItem 没有变化。然后我想通过 PATCH 发送所有所做的更改,但不发送未更改的字段。所以我需要从所有相同的字段中删除 editableItem selectedItem.

如何有效地做到这一点?我正在考虑使用 Underscore 递归遍历对象,但我真的很想知道在我解决它之前这是否是一种好的思考方式。

或者我可能会创建第三个对象,它只包含第二个对象的触摸字段,动态添加,但我不确定如何处理这个。

已编辑: 明确地说,我希望答案是通用的,并假设可能是最复杂的对象结构。例如,this question 的答案不适用于此处,因为它们要么假设对象只有简单的字段,要么需要分别为每个字段显式设置 Angular 观察者。

我用这样的函数做了类似的事情:

function getUpdateObject(orig, current) {
    varChanges = {};

    for (var prop in orig) {
        if (prop.indexOf("$") != 0 && orig[prop] !== current[prop]) {
            varChanges[prop] = current[prop];
        }
    }
    return varChanges ;
};

我认为这不会让你一路走下去。我没有在对象具有成员对象或数组的任何情况下使用它,但您应该能够测试 "prop" 是对象还是数组并递归调用它。我看到的关于该方法的最大警告是,如果你有一个深层的嵌套结构,你可能无法检测到变化,直到你下降了几个层次。您可能必须在内存中保留已更改 属性 的完整潜在层次结构,然后当您检测到较低级别的更改时,将整个层次结构写入输出对象。

这就是我的结局。也许它会帮助某人。我使用了 DeepDiff 库。代码在 CoffeScript 中,如果有人需要,应该很容易翻译成 JavaScript。

   $scope.getChangesObject = () ->
      selected = $scope.selectedItem
      editable = $scope.editableItem
      changes = {}
      differences = DeepDiff(selected, editable)

      for diff in differences
        formattedPath = ""
        for pathPart, index in diff.path
          if index isnt diff.path.length - 1
            formattedPath += pathPart + "."
          else
            formattedPath += pathPart
        changes[formattedPath] = editable[formattedPath]

      changes