无循环地为数组中的每个对象赋值

Assign a value to every object in an array without loop

我正在向 angular 1 个应用程序添加一个简单的评论组件。我从服务器获取的对象如下所示:

comments":[
        {"id":1,"content":"this is my first comment","approved":1,"replies":[]},
        {"id":2,"content":"this is the second","approved":1,"replies":[
          {"priority_id":0,"content":"content of a reply","approved":1},
          {"priority_id":0,"content":"content of a second reply","approved":1}]
        }
      ]

目前我在控制器中使用 2 个循环为每个评论分配一个 "pending" 值并回复 approved:0

看起来像这样:

angular.forEach($scope.comments, function (comment) {
          if (comment.approved === 0) {
            comment.pending = true;
        }
          comment.replies = comment.replies || [];

          angular.forEach(comment.replies, function (reply) {
          if (reply.approved === 0) {
            reply.pending = true;
            }
          });
      });

有没有更好、更短的方法来获得它? Javascript 不是我的强项。我真的需要在控制器中循环吗?也许我可以以某种方式传递 ng-repeat 的值?提前致谢!

感谢 Joe 我知道了一种比循环更好的方法。尽管我不得不稍微修改代码才能工作,但我已将他的答案标记为解决方案,因为我的应用程序使用 angular 1.4,它与箭头函数不兼容。这是代码:

$scope.comments.map(function(comment) {

                  if (comment.approved === 0) {
                    comment.pending = true;
                  }

                  comment.replies = comment.replies || [];

                  comment.replies.map(function(reply){
                     if (reply.approved === 0) {
                    reply.pending = true;
                    }
                    return reply.approved;
                  });
                  return comment.approved;

                });

它看起来不像 Joe 的那样整洁,但它仍然使用 map 方法,正如 Joe 和 Matthew 所建议的那样,它比循环更好。

所以不确定这是更清晰还是更简洁,但您可以利用数组上的 javascript .map 原型。 map 函数的作用是遍历数组并根据提供的函数将每个值转换为新值。所以这实际上是 return 从前一个数组映射而来的新对象数组。我不确定这是否真的更简单。您还可以利用 ES5 箭头功能。

另一件事: 在您当前的代码中,评论只有在 approved === 0 时才会获得 pending 字段。这意味着如果不等于 0,则评论中将不存在 pending 字段。如果你依赖这个字段,这可能会在以后导致奇怪的事情。有些人会说 pending 等于 true,而其他评论则未定义。您的回复也是如此。我下面的解决方案使用条件 AS 挂起字段,因此它存在于每个对象上,而不仅仅是真正的对象。

MDN:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

$scope.comments.map(comment => {
    comment.pending = comment.approved === 0;
    comment.replies = (comment.replies || []).map(reply => {
        reply.pending = reply.approved === 0;
        return reply;
    });
    return comment;
})

您可以编写一个函数,将该键添加到您的对象中。使用这个函数,你的循环将是这样的:

let comments = [{
  "id": 1,
  "content": "this is my first comment",
  "approved": 1,
  "replies": []
}, {
  "id": 2,
  "content": "this is the second",
  "approved": 1,
  "replies": [{
      "priority_id": 0,
      "content": "content of a reply",
      "approved": 1
    },
    {
      "priority_id": 0,
      "content": "content of a second reply",
      "approved": 1
    }
  ]
}, {
  "id": 3,
  "content": "this is the third",
  "approved": 0,
  "replies": [{
      "priority_id": 0,
      "content": "content of a reply",
      "approved": 0
    },
    {
      "priority_id": 0,
      "content": "content of a second reply",
      "approved": 0
    }
  ]
}];

function AddPending(obj) {
  obj['pending'] = true;
  return obj;
}

comments.forEach(function(comment) {

  comment = (comment.hasOwnProperty('approved') && comment.approved === 0) ? AddPending(comment) : comment;


  comment.replies = comment.replies || [];

  comment.replies.forEach(function(reply) {
    reply = (reply.approved === 0) ? AddPending(reply) : reply;
  });
});

console.log(comments);

您也可以升级此功能,它接收对象并检查条件,如果条件为真,则添加密钥。在 ng-repeat 上使用此功能。如下图

var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
  $scope.comments = [{
    "id": 1,
    "content": "this is my first comment",
    "approved": 1,
    "replies": []
  }, {
    "id": 2,
    "content": "this is the second",
    "approved": 1,
    "replies": [{
        "priority_id": 0,
        "content": "content of a reply",
        "approved": 1
      },
      {
        "priority_id": 0,
        "content": "content of a second reply",
        "approved": 1
      }
    ]
  }, {
    "id": 3,
    "content": "this is the third",
    "approved": 0,
    "replies": [{
        "priority_id": 0,
        "content": "content of a reply",
        "approved": 0
      },
      {
        "priority_id": 0,
        "content": "content of a second reply",
        "approved": 0
      }
    ]
  }];

  function AddPending(obj) {
    obj['pending'] = true;
    return obj;
  }

  $scope.f = function(comment) {
    comment = (comment.approved === 0) ? AddPending(comment) : comment;
    comment.replies = comment.replies || [];

    angular.forEach(comment.replies, function(reply) {
      reply = (reply.approved === 0) ? AddPending(reply) : reply;
    });
    return comment;
  };

});
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.js"></script>
<script src="script.js"></script>

<body>

  <div ng-app="myApp" ng-controller="myCtrl">
    <hr>
    <div ng-repeat="comment in comments track by $index">
      comment: {{f(comment)}}
      <hr>

    </div>

  </div>
</body>

</html>