为什么将 toArray 过滤器与 ng-repeat 和字符串对象一起使用会导致无限摘要循环?

Why using toArray filter with ng-repeat and an object of strings causes an infinite digest loop?

我想在遍历对象属性时将 orderBy 过滤器与 ng-repeat 指令一起使用。 由于 orderBy 过滤器仅适用于数组,Angular doc 建议使用 toArray 过滤器。

toArray 过滤器的工作原理非常棒,对象属性如下:

var obj = {
  a: { name: 'A' },
  b: { name: 'B' },
  c: { name: 'C' }
};

但是当与非对象属性一起使用时,它会导致无限摘要循环

var obj = {
  a: 'A',
  b: 'B',
  c: 'C'
};

这里 plunker 说明了这个问题。

无论如何你不应该那样做,过滤器在转换数据时通常不是个好主意,因为每次摘要循环进行循环时它都会被重新计算。你的 plunker 不起作用,所以很难说为什么,但看代码我会说它确实在每个摘要循环中创建了全新的数组,并且在对象的情况下它添加了 $key 属性,这有助于停止摘要循环。它不能将这样的 属性 添加到字符串中。但我不太确定。

编辑: 当您将 console.log 添加到 toArray:

return Object.keys(obj).map(function (key) {
        var value = obj[key];

        console.log(key, value);

        return angular.isObject(value) ?
          Object.defineProperty(value, '$key', { enumerable: false, value: key}) :
          { $key: key, $value: value };
      });

在日志中您可以看到问题的答案:

VM596 angular-toArrayFilter.js:15 b b
VM596 angular-toArrayFilter.js:15 a a
VM596 angular-toArrayFilter.js:15 c Object {p: "c"}
VM596 angular-toArrayFilter.js:15 b Object {p: "b"}
VM596 angular-toArrayFilter.js:15 a Object {p: "a"}
VM596 angular-toArrayFilter.js:15 c Object {p: "c", $key: "c"}
VM596 angular-toArrayFilter.js:15 b Object {p: "b", $key: "b"}
VM596 angular-toArrayFilter.js:15 a Object {p: "a", $key: "a"}
VM596 angular-toArrayFilter.js:15 c c
VM596 angular-toArrayFilter.js:15 b b
VM596 angular-toArrayFilter.js:15 a a
VM596 angular-toArrayFilter.js:15 c Object {p: "c", $$hashKey: "object:11", $key: "c"}
VM596 angular-toArrayFilter.js:15 b Object {p: "b", $$hashKey: "object:10", $key: "b"}
VM596 angular-toArrayFilter.js:15 a Object {p: "a", $$hashKey: "object:9", $key: "a"}

在 case objects 中,angular 使用相同的对象并且不会创建新的对象。这样它就可以假设数组没有改变并结束摘要循环。对于字符串值,它会在每次过滤器为 运行 时创建新对象,因此它假定每次都创建不同的数组,因此它无法结束摘要循环。