【问题标题】:Javascript: for..in loop running more number of times than expectedJavascript:for..in 循环运行的次数超出预期
【发布时间】:2017-03-31 14:31:12
【问题描述】:

在下面的代码中,user.roles 的实际长度为 1。但是,循环运行了两次。

当我输出 i 的值时,它在第二次迭代中显示为 'diff'。 切换到普通的 for 循环解决了这种情况。 但是,我想知道 for..in 循环有什么问题。

 for (var i in user.roles) {
                if (user.roles[i].school.equals(schoolId)) {
                    for (var j in user.roles[i].permissions) {
                        for (var k in accessType) {
                            if (user.roles[i].permissions[j].feature == featureKey) {
                                if (user.roles[i].permissions[j][accessType[k]]) {
                                    return true;
                                }
                            }
                        }
                    }
                }
            }

更新:用户是一个对象,角色是一个对象数组。导致问题的角色实例如下所示:

{
  "_id": "582d3390d572d05c1f028f53",
  "displayName": "Test Teacher Attendance",
  "gender": "Male",
  "roles": [
    {
      "_id": "57a1b3ccc71009c62a48a684",
      "school": "57a1b3ccc71009c62a48a682",
      "role": "Teacher",
      "__v": 0,
      "designation": true,
      "permissions": [
        {
          "feature": "User",
          "_id": "57ac0b9171b8f0b82befdb7d",
          "review": false,
          "view": true,
          "delete": false,
          "edit": false,
          "create": false
        },
        {
          "feature": "Notice",
          "_id": "57ac0b9171b8f0b82befdb7c",
          "review": false,
          "view": true,
          "delete": false,
          "edit": false,
          "create": false
        },

      ]
    }
  ],
}

【问题讨论】:

  • 你能定义用户、角色、权限、访问类型吗?这些是对象、字符串、整数。
  • user.roles 是一个数组/迭代器吗?也许你应该使用for .. of
  • 你为什么使用for in?尝试使用 forEach 。它更方便。 stackoverflow.com/questions/23614054/…
  • @Teocci user.roles 是对象数组,权限是 user.roles 中的对象数组。 accessType 是一个字符串数组。
  • @AllenGJ 你能把我的问题标记为答案吗?

标签: javascript arrays node.js for-loop


【解决方案1】:

user.roles 似乎是一个数组。而对于数组,你不应该使用 for in。

简单示例

var arr = [2];
arr.s = 3;

for (var i  in arr) {
console.log("here"); // paints twice
}

来自MDNfor...in 语句以任意顺序迭代对象的可枚举属性。对于每个不同的属性,可以执行语句。

如何选择迭代器的类型,这里参考iterators

编辑

根据更新后的问题,如果以下代码中的某处存在,则上述内容只能带有 diff 属性

Array.prototype.diff = .....

【讨论】:

  • 谢谢。但是,在这种情况下, user.roles 似乎只有一个可编号的属性,对吧?即,它只有一个对象。当我控制 i 的值时,对于第二次(意外)迭代,它保存值 'diff'。
  • 如果是这种情况,那么您的代码中一定有Array.prototype.diff
  • @AllenGJ - 你检查了吗?此外,您可以通过delete Array.prototype.diff; 将其删除
【解决方案2】:

我想这就是你要找的。 我假设您的 accessTypes 是一个包含以下项目的数组:

var accessTypes = ["review", "view", "delete", "edit", "create"];

编辑以提高效率。

var schoolId = "57a1b3ccc71009c62a48a682";
var featureKey = "Notice";
var accessTypes = ["review", "view", "delete", "edit", "create"];

var user = {
  "_id": "582d3390d572d05c1f028f53",
  "displayName": "Test Teacher Attendance",
  "gender": "Male",
  "roles": [{
    "_id": "57a1b3ccc71009c62a48a684",
    "school": "57a1b3ccc71009c62a48a682",
    "role": "Teacher",
    "__v": 0,
    "designation": true,
    "permissions": [{
      "feature": "User",
      "_id": "57ac0b9171b8f0b82befdb7d",
      "review": false,
      "view": true,
      "delete": false,
      "edit": false,
      "create": false
    }, {
      "feature": "Notice",
      "_id": "57ac0b9171b8f0b82befdb7c",
      "review": false,
      "view": true,
      "delete": false,
      "edit": false,
      "create": false
    }]
  }]
};

user.roles.forEach(function(roleItem) {
  // console.log('This is a role: ' + roleItem.school);
  if (roleItem.school == schoolId) {
    roleItem.permissions.forEach(function(permissionItem) {
      // console.log('This is a permission: ' + permissionItem.feature);
      // console.log('This is a accessType: ' + accessType);
      if (permissionItem.feature == featureKey) {
        accessTypes.forEach(function(accessType) {
          if (permissionItem[accessType]) {
            console.log('accessType: ' + accessType + ' -> true');
            return true;
          }
        });
      }
    });
  }
});

forEach 接受迭代器函数。为数组中的每个条目调用迭代器函数,按顺序跳过稀疏数组中不存在的条目。

forEach 还有一个好处是,您不必在包含范围内声明索引和值变量,因为它们作为参数提供给迭代函数,因此很好地限定了该迭代。

如果您担心为每个数组条目进行函数调用的运行时成本,请不要担心;更多technical details.

如果您仍然认为forEach 的速度基本上较慢,您可以使用一个简单的for 循环,正如我在另一个my answers 中解释的那样。

希望对您有所帮助。

【讨论】:

  • 性能怎么样?我的印象是 forEach 从根本上来说更慢。
  • @AllenGJ 如果您仍然觉得forEach 速度较慢,您可以使用一个简单的for 循环,正如我在另一个Answer 中解释的那样。
猜你喜欢
  • 2019-05-05
  • 1970-01-01
  • 1970-01-01
  • 2016-04-07
  • 2020-07-28
  • 2019-10-14
  • 1970-01-01
  • 2016-07-19
  • 2012-05-28
相关资源
最近更新 更多