【问题标题】:Assign a value to every object in an array without loop为数组中的每个对象赋值,无需循环
【发布时间】:2018-10-26 16:40:02
【问题描述】:

我正在向 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 个循环为每个评论分配一个“待定”值,并回复已批准: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 arrays angularjs object angularjs-ng-repeat


    【解决方案1】:

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

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

    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;
    })
    

    【讨论】:

    • 使用 map 等函数的缩短代码通常会使函数更简洁、更易于阅读。我投了赞成票。
    • 这就是我的想法,但不确定 OP 是否想要更少的代码或没有循环。感谢您的支持!
    【解决方案2】:

    您可以编写一个函数,将该键添加到您的对象中。使用此函数,您的循环将如下所示:

    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>

    【讨论】:

      猜你喜欢
      • 2012-11-19
      • 2014-01-02
      • 1970-01-01
      • 1970-01-01
      • 2017-08-04
      • 1970-01-01
      • 1970-01-01
      • 2016-01-17
      • 2015-03-16
      相关资源
      最近更新 更多