2016-11-17 4 views
6

Im folgenden Code ist die tatsächliche Länge von user.roles 1. Die Schleife wird jedoch zweimal ausgeführt.Javascript: for..in Schleife läuft mehr Male als erwartet

Wenn ich den Wert von i ausgabe, wird es als 'diff' für die zweite Iteration angezeigt. Die Umstellung auf die normale for-Schleife löste die Situation. Allerdings würde ich gerne wissen, was das Problem mit der for..in Schleife ist.

Update: Benutzer ist ein Objekt und Rollen ist ein Array von Objekten. Die Instanz von Rollen, die das Problem verursacht wird unten dargestellt:

{ 
    "_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 
     }, 

     ] 
    } 
    ], 
} 
+0

können Sie Benutzer, Rollen, Berechtigungen, accessType definieren? das sind Objekte, Strings, ganze Zahlen. – Teocci

+0

Ist 'user.roles' ein Array/Iterator? Vielleicht solltest du 'for .. of' verwenden. – zeronone

+0

Warum benutzt du' for in'? versuche 'forEach' zu verwenden. Es ist bequemer. http://stackoverflow.com/questions/23614054/javascript-nuances-of-myarray-foreach-vs-for-loop –

Antwort

2

user.roles scheint ein Array zu sein. Und für Array sollten Sie nicht für die Verwendung in.

Einfaches Beispiel

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

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

Von MDN, Der für ... in Anweisung iteriert über die zählbaren Eigenschaften eines Objekt, in beliebiger Reihenfolge. Für jede einzelne Eigenschaft können Anweisungen ausgeführt werden.

Wie die Art des Iterator zu wählen, hier ist eine Referenz iterators

EDIT

Gemäß der Frage aktualisiert wird, können die oben nur mit einer Eigenschaft als diff kommen, wenn irgendwo im Code folgende vorhanden ist

Array.prototype.diff = ..... 
+0

Danke. In diesem Fall scheint user.roles jedoch nur eine enumerierbare Eigenschaft zu haben, oder? dh es hat nur ein Objekt in sich. Wenn ich den Wert von ** i ** für die zweite (unerwartete) Iteration trete, hält es den Wert ** ** diff ** '. –

+0

Wenn das der Fall ist, muss irgendwo in Ihrem Code 'Array.prototype.diff' stehen. – nikhil

+0

@AllenGJ - Haben Sie überprüft? Zusätzlich können Sie es mit 'delete Array.prototype.diff;' – nikhil

2

ich denke, das ist das, was Sie suchen. Ich gehe davon aus, dass Ihr accessTypes ein Array ist, das die folgenden Elemente enthält:

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

Edited die Effizienz zu verbessern.

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 akzeptiert eine Iterator-Funktion. Die Iterator-Funktion wird für jeden Eintrag im Array in der Reihenfolge aufgerufen, in der nicht existierende Einträge in Sparse-Arrays übersprungen werden.

forEach hat auch den Vorteil, dass Sie keine Indizierungs- und Wertvariablen im enthaltenden Bereich deklarieren müssen, da sie als Argumente für die Iterationsfunktion bereitgestellt werden und so genau auf diese Iteration beschränkt sind.

Wenn Sie sich Sorgen machen über die Laufzeitkosten für einen Funktionsaufruf für jeden Array-Eintrag, seien Sie nicht; mehr technical details.

Wenn Sie immer noch den Eindruck haben, dass forEach wesentlich langsamer ist, können Sie eine einfache for Schleife verwenden, wie ich in einem anderen von my answers erkläre.

Hoffe, dass dies Ihnen hilft.

+0

löschen. Was ist mit der Leistung? Ich hatte den Eindruck, dass forEach grundsätzlich langsamer ist. –

+0

@AllenGJ Wenn Sie immer noch den Eindruck haben, dass 'forEach' grundsätzlich langsamer ist, können Sie eine einfache 'for'-Schleife verwenden, wie ich in einer anderen [Antwort] (http://stackoverflow.com/questions/40647538/#40647652) erkläre. – Teocci

Verwandte Themen