Hoe kan ik een JavaScript-object doorlopen of opsommen?

Ik heb een JavaScript-object zoals het volgende:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

Nu wil ik alle p-elementen doorlopen (p1, p2, p3…) En krijgen hun sleutels en waarden. Hoe kan ik dat doen?

Ik kan het JavaScript-object indien nodig wijzigen. Mijn uiteindelijke doel is om een aantal sleutelwaardeparen te doorlopen en indien mogelijk wil ik het gebruik van evalvermijden.


Antwoord 1, autoriteit 100%

U kunt de for-inlus zoals door anderen getoond. Je moet er echter ook voor zorgen dat de sleutel die je krijgt een echte eigenschap van een object is en niet afkomstig is van het prototype.

Hier is het fragment:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};
for (var key in p) {
    if (p.hasOwnProperty(key)) {
        console.log(key + " -> " + p[key]);
    }
}

Antwoord 2, autoriteit 26%

Onder ECMAScript 5 kunt u Object.keys()en Array.prototype.forEach():

var obj = { first: "John", last: "Doe" };
Object.keys(obj).forEach(function(key) {
    console.log(key, obj[key]);
});

Ecmascript 6 voegt for...of:

for (const key of Object.keys(obj)) {
    console.log(key, obj[key]);
}

Ecmascript 8 voegt Object.entries()die vermijdt elke waarde op te zoeken in het originele object:

Object.entries(obj).forEach(
    ([key, value]) => console.log(key, value)
);

U kunt for...of, destructureren en Object.entries:

for (const [key, value] of Object.entries(obj)) {
    console.log(key, value);
}

Beide Object.keys()EN Object.entries()Herstenen in dezelfde volgorde als een for...inlus maar negeer de prototypeketen . Alleen de eigen traaglijke eigenschappen van het object zijn geïllustreerd.


3, Autoriteit 7%

U moet de voor-in-in-lus

gebruiken

Maar wees heel voorzichtig bij het gebruik van dit soort lus, omdat dit alle eigenschappen langs de prototype keten zal gebruiken.

Gebruik daarom bij het gebruik van for-in-lussen altijd de methode hasOwnPropertyom te bepalen of de huidige eigenschap in iteratie echt een eigenschap is van het object dat u controleert:

for (var prop in p) {
    if (!p.hasOwnProperty(prop)) {
        //The current property is not a direct property of p
        continue;
    }
    //Do your logic with the property here
}

Antwoord 4

Voorwoord:

  • Objecteigenschappen kunnen eigenzijn (de eigenschap bevindt zich op het object zelf) of geërfd(niet op het object zelf, op een van de prototypes).
  • Objecteigenschappen kunnen opsombaarof niet-opsombaarzijn. Niet-opsombare eigenschappen worden weggelaten uit veel opsommingen/arrays van eigenschappen.
  • Eigenschapsnamen kunnen tekenreeksen of symbolen zijn. Eigenschappen waarvan de namen Symbolen zijn, zijn weggelaten uit veel opsommingen/arrays van eigenschappen.

Hier in 2018 zijn uw opties voor het doorlopen van de eigenschappen van een object (sommige voorbeelden volgen de lijst):

  1. for-in[MDN, spec] — Een lusstructuur die door de namen van de opsombareeigenschappen van een object loopt, inclusief geërfde eigenschappen, waarvan de namen strings zijn
  2. Object.keys[MDN, spec] — Een functie die een array levert van de namen van de eigen, enumerableeigenschappen van een object waarvan de namen strings zijn.
  3. Object.values[MDN, spec] — Een functie die een array levert van de waardenvan de eigen, enumerableeigenschappen van een object.
  4. Object.entries[MDN spec ] – Een functie verschaffen van een array van namen en waarden eigen , opgesomd eigenschappen (elk item in de array een [name, value]array).
  5. Object.getOwnPropertyNames[MDN spec ] – Een functie die zorgt voor een serie van de namen van de eigen eigenschappen (zelfs niet-opsombare degenen) van een object waarvan de namen zijn strings.
  6. Object.getOwnPropertySymbols[MDN spec ] – Een functie die zorgt voor een serie van de namen van de eigen eigenschappen (zelfs niet-opsombare degenen) van een object waarvan de namen zijn symbolen.
  7. Reflect.ownKeys[MDN spec ] – Een functie die zorgt voor een serie van de namen van de eigen eigenschappen (zelfs niet-opsombare degenen) van een object, ongeacht of deze namen zijn strings of symbolen.
  8. Als u alleeigenschappen van een object wilt, inclusief niet-opsombare geërfde eigenschappen, moet u een lus gebruiken en Object.getPrototypeOf[MDN, spec] en gebruik Object.getOwnPropertyNames, Object.getOwnPropertySymbolsof Reflect.ownKeysop elk object in de prototypeketen (voorbeeld onderaan dit antwoord).

Met alle behalve for-in, zou je een soort looping-constructie op de array gebruiken (for, for-of, forEach, enz.).

Voorbeelden:

for-in:


Antwoord 5

In ECMAScript 5 heb je een nieuwe benadering in iteratievelden van letterlijk – Object.keys

Meer informatie vindt u op MDN

Mijn keuze is hieronder als een snellere oplossing in huidige versies van browsers (Chrome30, IE10, FF25)

var keys = Object.keys(p),
    len = keys.length,
    i = 0,
    prop,
    value;
while (i < len) {
    prop = keys[i];
    value = p[prop];
    i += 1;
}

Je kunt de prestaties van deze aanpak vergelijken met verschillende implementaties op jsperf.com:

Browserondersteuning die u kunt zien op Kangax’s compattabel

Voor de oude browser heb je eenvoudigeen volledigepolyfill

UPD:

prestatievergelijking voor alle meest populaire gevallen in deze vraag op perfjs.info:

letterlijke iteratie van het object


Antwoord 6

Je kunt het gewoon herhalen als:

for (var key in p) {
  alert(p[key]);
}

Houd er rekening mee dat keyniet de waarde van de eigenschap overneemt, het is slechts een indexwaarde.


Antwoord 7

Sinds es2015 steeds populairder wordt, plaats ik dit antwoord, inclusief het gebruik van generator en iterator om soepel door [key, value]-paren te itereren. Zoals het mogelijk is in andere talen, bijvoorbeeld Ruby.

Ok, hier is een code:

const MyObject = {
  'a': 'Hello',
  'b': 'it\'s',
  'c': 'me',
  'd': 'you',
  'e': 'looking',
  'f': 'for',
  [Symbol.iterator]: function*() {
    for (const i of Object.keys(this)) {
      yield [i, this[i]];
    }
  }
};
for (const [k, v] of MyObject) {
  console.log(`Here is key ${k} and here is value ${v}`);
}

8

Prestaties

Vandaag 2020.03.06 Ik voer tests uit gekozen oplossingen op Chrome V80.0, Safari V13.0.5 en Firefox 73.0.1 op MacOS High Sierra V10.13.6

Conclusies

  • Oplossingen op basis van for-in(A, B) zijn snel (of snel) voor alle browsers voor grote en kleine objecten
  • verrassend for-of(H) -oplossing is snel op chroom voor kleine en grote objecten
  • Solutions op basis van expliciete index i(J, K) zijn vrij snel op alle browsers voor kleine objecten (voor Firefox ook snel voor grote OJBECTS maar Medium snel op andere browsers)
  • Oplossingen op basis van iterators (D, E) zijn langzaamst en niet aanbevolen
  • Oplossing C is traag voor grote voorwerpen en middellange traag voor kleine objecten

Details

Performance-tests zijn uitgevoerd voor

  • Small Object – Met 3 velden – U kunt de test uitvoeren op uw machine hier
  • ‘Big’ object – Met 1000 velden – U kunt de test uitvoeren op uw machine hier

Hieronder tafsluitingen presenteert gebruikte oplossingen


9

for(key in p) {
  alert( p[key] );
}

Opmerking: u kunt dit boven arrays doen, maar u hanteert ook over de lengthen andere eigenschappen.


10

Na alle antwoorden hier te hebben bekeken, is hasOwnProperty niet vereist voor mijn eigen gebruik omdat mijn json-object schoon is; het heeft echt geen zin om extra javascript-verwerking toe te voegen. Dit is alles wat ik gebruik:

for (var key in p) {
    console.log(key + ' => ' + p[key]);
    // key is key
    // value is p[key]
}

Antwoord 11

via prototypemet forEach()die de eigenschappen van de prototypeketenmoeten overslaan:

Object.prototype.each = function(f) {
    var obj = this
    Object.keys(obj).forEach( function(key) { 
        f( key , obj[key] ) 
    });
}
//print all keys and values
var obj = {a:1,b:2,c:3}
obj.each(function(key,value) { console.log(key + " " + value) });
// a 1
// b 2
// c 3

Antwoord 12

Het is interessant dat mensen in deze antwoorden zowel Object.keys()als for...ofhebben aangeraakt, maar ze nooit hebben gecombineerd:

var map = {well:'hello', there:'!'};
for (let key of Object.keys(map))
    console.log(key + ':' + map[key]);

Je kunt niet zomaar for...ofeen Objectomdat het geen iterator is, en for...indexof .forEach()het gebruik van Object.keys()is lelijk/inefficiënt.
Ik ben blij dat de meeste mensen afzien van for...in(met of zonder het aanvinken van .hasOwnProperty()), want dat is ook een beetje rommelig, dus anders dan mijn antwoord hierboven, ik ben hier om te zeggen…


U kunt gewone objectsverenigingen maken, itereren! Gedraag je net als Maps met direct gebruik van de fancy for...of
Demo Werken in Chrome en FF (ik neem alleen aan ES6)

var ordinaryObject = {well:'hello', there:'!'};
for (let pair of ordinaryObject)
    //key:value
    console.log(pair[0] + ':' + pair[1]);
//or
for (let [key, value] of ordinaryObject)
    console.log(key + ':' + value);

Zolang u mijn shim hieronder opneemt:

//makes all objects iterable just like Maps!!! YAY
//iterates over Object.keys() (which already ignores prototype chain for us)
Object.prototype[Symbol.iterator] = function() {
    var keys = Object.keys(this)[Symbol.iterator]();
    var obj = this;
    var output;
    return {next:function() {
        if (!(output = keys.next()).done)
            output.value = [output.value, obj[output.value]];
        return output;
    }};
};

Zonder een echt kaartobject te maken dat niet de leuke syntactische suiker heeft.

var trueMap = new Map([['well', 'hello'], ['there', '!']]);
for (let pair of trueMap)
    console.log(pair[0] + ':' + pair[1]);

In feite, met deze shim, als je nog steeds wilt profiteren van de andere functionaliteit van de kaart (zonder ze allemaal in te schakelen) maar nog steeds wilde het note-objectnotatie gebruiken, omdat objecten nu iespubliek zijn, kun je nu gewoon een kaart maken van het!

//shown in demo
var realMap = new Map({well:'hello', there:'!'});

Voor degenen die niet van shim houden, of in het algemeen niet met prototypeknoeien, voel je vrij om de functie in plaats daarvan in het venster te maken, door het iets te noemen als getObjIterator()dan;

//no prototype manipulation
function getObjIterator(obj) {
    //create a dummy object instead of adding functionality to all objects
    var iterator = new Object();
    //give it what the shim does but as its own local property
    iterator[Symbol.iterator] = function() {
        var keys = Object.keys(obj)[Symbol.iterator]();
        var output;
        return {next:function() {
            if (!(output = keys.next()).done)
                output.value = [output.value, obj[output.value]];
            return output;
        }};
    };
    return iterator;
}

Nu kun je het gewoon een gewone functie noemen, er wordt verder niets beïnvloed

var realMap = new Map(getObjIterator({well:'hello', there:'!'}))

of

for (let pair of getObjIterator(ordinaryObject))

Er is geen reden waarom dat niet zou werken.

Welkom in de toekomst.


Antwoord 13

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};
for (var key in p) {
    if (p.hasOwnProperty(key)) {
        console.log(key + " = " + p[key]);
    }
}
<p>
  Output:<br>
  p1 = values1<br>
  p2 = values2<br>
  p3 = values3
</p>

Antwoord 14

Je kunt ook Object.keys() gebruiken en de objectsleutels herhalen zoals hieronder om de waarde te krijgen:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};
Object.keys(p).forEach((key)=> {
 console.log(key +' -> '+ p[key]);
});

Antwoord 15

Object.keys(obj): Array

haalt alle sleutels met tekenreekswaarde op van alle opsombare eigen (niet-overgenomen) eigenschappen.

Het geeft dus dezelfde lijst met sleutels als u van plan bent door elke objectsleutel te testen met hasOwnProperty. Je hebt die extra testoperatie niet nodig dan en Object.keys( obj ).forEach(function( key ){})zou sneller moeten zijn. Laten we het bewijzen:

var uniqid = function(){
			var text = "",
					i = 0,
					possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
			for( ; i < 32; i++ ) {
					text += possible.charAt( Math.floor( Math.random() * possible.length ) );
			}
			return text;
		}, 
		CYCLES = 100000,
		obj = {}, 
		p1,
		p2,
		p3,
		key;
// Populate object with random properties
Array.apply( null, Array( CYCLES ) ).forEach(function(){
	obj[ uniqid() ] = new Date()
});
// Approach #1
p1 = performance.now();
Object.keys( obj ).forEach(function( key ){
	var waste = obj[ key ];
});
p2 = performance.now();
console.log( "Object.keys approach took " + (p2 - p1) + " milliseconds.");
// Approach #2
for( key in obj ) {
	if ( obj.hasOwnProperty( key ) ) {
		var waste = obj[ key ];
	}
}
p3 = performance.now();
console.log( "for...in/hasOwnProperty approach took " + (p3 - p2) + " milliseconds.");

Antwoord 16

Alleen JavaScript-code zonder afhankelijkheden:

var p = {"p1": "value1", "p2": "value2", "p3": "value3"};
keys = Object.keys(p);   // ["p1", "p2", "p3"]
for(i = 0; i < keys.length; i++){
  console.log(keys[i] + "=" + p[keys[i]]);   // p1=value1, p2=value2, p3=value3
}

Antwoord 17

In het nieuwste ES-script kun je zoiets als dit doen:

let p = {foo: "bar"};
for (let [key, value] of Object.entries(p)) {
  console.log(key, value);
}

Antwoord 18

Hier is een andere methode om een object te doorlopen.

  var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};
Object.keys(p).forEach(key => { console.log(key, p[key]) })

Antwoord 19

Een for-ofgebruiken op Object.keys()

Vind ik leuk:

let object = {
  "key1": "value1",
  "key2": "value2",
  "key3": "value3"
};
for (let key of Object.keys(object)) {
  console.log(key + " : " + object[key])
}

Antwoord 20

U kunt een eenvoudige functie forEachaan alle objecten toevoegen, zodat u automatisch door elk object kunt bladeren:

Object.defineProperty(Object.prototype, 'forEach', {
    value: function (func) {
        for (var key in this) {
            if (!this.hasOwnProperty(key)) {
                // skip loop if the property is from prototype
                continue;
            }
            var value = this[key];
            func(key, value);
        }
    },
    enumerable: false
});

Voor die mensen die de “for … in“-methode niet leuk vinden:

Object.defineProperty(Object.prototype, 'forEach', {
    value: function (func) {
        var arr = Object.keys(this);
        for (var i = 0; i < arr.length; i++) {
            var key = arr[i];
            func(key, this[key]);
        }
    },
    enumerable: false
});

Nu kunt u eenvoudig bellen:

p.forEach (function(key, value){
    console.log ("Key: " + key);
    console.log ("Value: " + value);
});

Als u geen conflicten wilt krijgen met andere forEach-methoden, kunt u deze een naam geven met uw unieke naam.


Antwoord 21

Meerdere manieren om een object in javascript te herhalen

Gebruik for…inloop

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};
for (let key in p){
   if(p.hasOwnProperty(key)){
     console.log(`${key} : ${p[key]}`)
   }
}

Antwoord 22

Loops kunnen behoorlijk interessant zijn als je puur JavaScript gebruikt. Het lijkt erop dat alleen ECMA6 (Nieuwe JavaScript-specificatie uit 2015) de lussen onder controle kreeg. Helaas, terwijl ik dit schrijf, worstelen zowel browsers als de populaire geïntegreerde ontwikkelomgeving (IDE) nog steeds met het volledig ondersteunen van de nieuwe toeters en bellen.

Hier ziet u in één oogopslag hoe een JavaScript-objectlus eruitziet vóór ECMA6:

for (var key in object) {
  if (p.hasOwnProperty(key)) {
    var value = object[key];
    console.log(key); // This is the key;
    console.log(value); // This is the value;
  }
}

Ik weet ook dat dit buiten het bereik van deze vraag valt, maar in 2011 voegde ECMAScript 5.1 de forEach-methode toe voor alleen arrays, wat in feite een nieuwe verbeterde manier creëerde om door arrays te lussen terwijl er nog steeds geen itereerbare objecten met de oude uitgebreide en verwarrende for-lus. Maar het vreemde is dat deze nieuwe forEach-methode breakniet ondersteunt, wat tot allerlei andere problemen heeft geleid.

In principe is er in 2011 geen echt solide manier om JavaScript in een lus te plaatsen, behalve wat veel populaire bibliotheken (jQuery, Underscore, etc.) besloten opnieuw te implementeren.

Vanaf 2015 hebben we nu een betere kant-en-klare manier om elk objecttype (inclusief arrays en strings) te herhalen (en te breken). Dit is hoe een lus in JavaScript er uiteindelijk uit zal zien wanneer de aanbeveling mainstream wordt:

for (let [key, value] of Object.entries(object)) {
    console.log(key); // This is the key;
    console.log(value); // This is the value;
}

Houd er rekening mee dat de meeste browsers de bovenstaande code vanaf 18 juni 2016 niet meer ondersteunen. Zelfs in Chrome moet je deze speciale vlag inschakelen om het te laten werken: chrome://flags/#enable-javascript-harmony

Totdat dit de nieuwe standaard wordt, kan de oude methode nog steeds worden gebruikt, maar er zijn ook alternatieven in populaire bibliotheken of zelfs lichtgewicht alternatievenvoor degenen die geen van deze bibliotheken gebruiken.


Antwoord 23

In ES6 hebben we bekende symbolen om enkele eerder interne methoden bloot te leggen, je kunt het gebruiken om te definiëren hoe iterators voor dit object werken:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3",
    *[Symbol.iterator]() {
        yield *Object.keys(this);
    }
};
[...p] //["p1", "p2", "p3"]

Hiermee geeft u hetzelfde resultaat als gebruik van … in ES6-lus.

for(var key in p) {
    console.log(key);
}

Maar het is belangrijk om de mogelijkheden te kennen die u nu hebt gebruikt ES6!


24

Ik zou dit doen in plaats van het controleren van obj.hasOwnerPropertybinnen elke for...inlus.

var obj = {a : 1};
for(var key in obj){
    //obj.hasOwnProperty(key) is not needed.
    console.log(key);
}
//then check if anybody has messed the native object. Put this code at the end of the page.
for(var key in Object){
    throw new Error("Please don't extend the native object");
}

25

   var p =[{"username":"ordermanageadmin","user_id":"2","resource_id":"Magento_Sales::actions"},
{"username":"ordermanageadmin_1","user_id":"3","resource_id":"Magento_Sales::actions"}]
for(var value in p) {
    for (var key in value) {
        if (p.hasOwnProperty(key)) {
            console.log(key + " -> " + p[key]);
        }
    }
}

26

Een goede manier voor looping op een traaglijk JavaScript-object dat geweldig kan zijn en gebruikelijk voor reactersnelheden gebruikt Object.keysof Object.entriesmet behulp van mapFunctie. Zoals hieronder:

// assume items:
const items = {
  first: { name: 'phone', price: 400 },
  second: { name: 'tv', price: 300 },
  third: { name: 'sofa', price: 250 },
};

Voor looping en toon wat UI op ReactJSzoals hieronder:

~~~
<div>
  {Object.entries(items).map(([key, ({ name, price })]) => (
    <div key={key}>
     <span>name: {name}</span>
     <span>price: {price}</span>
    </div>
  ))}
</div>

Eigenlijk gebruik ik de destructuring-opdracht twee keer, eenmaal voor het verkrijgen van keyeenmaal voor het verkrijgen van nameEN price.


27

Als u wilt herhalen over Niet-traaglijke eigenschappen ook, u kunt Object.getOwnPropertyNames(obj)om een ​​reeks van alle eigendommen (traagbaar of niet) rechtstreeks op een bepaald object te retourneren.

var obj = Object.create({}, {
  // non-enumerable property
  getFoo: {
    value: function() { return this.foo; },
    enumerable: false
  }
});
obj.foo = 1; // enumerable property
Object.getOwnPropertyNames(obj).forEach(function (name) {
  document.write(name + ': ' + obj[name] + '<br/>');
});

28

Als iemand moet worden uitgevoerd door ArrayObjects met Conditie :

var arrayObjects = [{"building":"A", "status":"good"},{"building":"B","status":"horrible"}];
for (var i=0; i< arrayObjects.length; i++) {
  console.log(arrayObjects[i]);
  for(key in arrayObjects[i]) {      
      if (key == "status" && arrayObjects[i][key] == "good") {
          console.log(key + "->" + arrayObjects[i][key]);
      }else{
          console.log("nothing found");
      }
   }
}

Other episodes