angularjs$watch旧值和新值相同

angularjs$watch旧值和新值相同,angularjs,Angularjs,我的意图是观察范围内的模型,并找出旧值和新值之间的差异 但是,我从下面的代码中发现旧值和新值都是相同的 app.controller('MyCtrl', function($scope, $timeout){ $scope.markers = {}; $scope.$watchCollection('markers', function(newValue, oldValue){ console.log('being watched oldValue:', oldValue, 'n

我的意图是观察范围内的模型,并找出旧值和新值之间的差异

但是,我从下面的代码中发现旧值和新值都是相同的

app.controller('MyCtrl', function($scope, $timeout){
  $scope.markers = {};
  $scope.$watchCollection('markers', function(newValue, oldValue){
    console.log('being watched oldValue:', oldValue, 'newValue:', newValue);
  });
  $timeout( function() {
    $scope.markers.foo = 1;
  }, 500);
  $timeout( function() {
    $scope.markers.bar = 2;
  }, 500);
});
输出:

being watched oldValue: Object {} newValue: Object {} script.js:6
being watched oldValue: Object {foo: 1} newValue: Object {foo: 1} script.js:6
being watched oldValue: Object {foo: 1, bar: 2} newValue: Object {foo: 1, bar: 2} 
为什么它们是一样的,如果是故意的,为什么


下面是代码,

您可以使用
$watch
来代替,这似乎很有效。如果您想同时查看对象上的所有属性(正如您所做的),则需要将
true
作为第三个参数添加到监视中。这是一个深表

JS:

这是一个错误


而且它似乎不是固定的。

这些值作为参数传递

$scope.$watch('foo', function (newValue, oldValue) {
  // ...
}

我发现检查新值和旧值(值)是否相等非常有用,如果是这样,则跳过该过程以避免意外行为。你可以用它来实现这一点。下面是一个例子:

JS:


watchCollection的文档说明:“Shallow监视对象的属性,并在任何属性更改时激发(对于数组,这意味着监视数组项;对于对象映射,这意味着监视属性)。”。因此,在对象上使用watchCollection是正确的。@JBNizet奇怪,我确实尝试先对watchCollection进行深度监视(添加true),但没有成功。不过,常规深度观察确实有效。:)我已经编辑了答案,所以我不会在这两个之间做假设。JB,watchCollection被破坏了。是的,当属性更改时触发,否,它不会保存旧值以返回它们,如文档中所指定。相反,您将在一个新的单独对象中获得新数据的副本。文档不是最新的,或者是一个bug
newValue===oldValue
声明
false
,因此我倾向于认为这是一个bug。事实证明这是一个已知的bug:我假设$watchCollection是deep$watch的捷径。似乎不是。太好了,我浪费了十分钟的生命。谢谢你的提问,节省了我很多时间。:)现在已经修好了:当心!这是一种非常糟糕的做法,在某些情况下很容易导致问题。例如,当第一次设置监视的属性(即从未定义转换为某个值)时,将调用监视侦听器,并将newValue和oldValue bot设置为新值,如果存在此检查,则将忽略更改。您可以在此处阅读更多关于此的信息:
$scope.$watch('foo', function (newValue, oldValue) {
  // ...
}
$scope.$watch('myObject', function(newValue, oldValue){
    if(angular.equals(newValue, oldValue)){
        return; // simply skip that
    }
});