For..In loops w JavaScript - pary klucz-wartość

414

Zastanawiałem się, czy istnieje sposób zrobienia czegoś takiego jak foreachpętla PHP w JavaScript. Funkcjonalność, której szukam, to coś w rodzaju tego fragmentu kodu PHP:

foreach($data as $key => $value) { }

Patrzyłem na for..inpętlę JS , ale wydaje się, że nie ma sposobu, aby określić as. Jeśli zrobię to za pomocą „normal” for loop ( for(var i = 0; i < data.length; i++), czy istnieje sposób na pobranie par klucz => wartości?

kabaret
źródło

Odpowiedzi:

215

Jeśli możesz użyć ES6 natywnie lub z Babelem (kompilatorem js), możesz wykonać następujące czynności:

const test = {a: 1, b: 2, c: 3};

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

Który wydrukuje ten wynik:

a 1
b 2
c 3

Object.entries()Metoda zwraca tablicę własność przeliczalnego danego obiektu[key, value] parach, w takiej samej kolejności jak te dostarczane przez for...inpętlę (z tą różnicą, że do pętli w wylicza właściwości łańcucha prototypu również) .

Mam nadzieję, że to pomoże! =)

Francesco Casula
źródło
1
Działa to idealnie, tylko się zastanawiam - w porównaniu do „dla klucza w obiekcie, a następnie uzyskaj wartość według obiektu [klucz]”, który z nich daje lepszą wydajność?
lsheng
1
W tym konkretnym przypadku zakładam, że jest wolniejszy z powodu Object.entriespołączenia. Nie przeprowadziłem jednak żadnych testów.
Francesco Casula
6
to najlepsza odpowiedź na pytanie, które dotyczyło chwytania zarówno klucza, jak i wartości w pętli for.
cipak
4
Przyjęta odpowiedź powinna zostać zaktualizowana, ponieważ faktycznie odpowiada na pytanie, chociaż nie była dostępna w momencie pytania.
Marc Qualie
1
Możesz sprawdzić to pytanie: stackoverflow.com/questions/47213651/…, co wydaje się wskazywać, że zalecana byłaby składnia tego typu: Object.keys (myObject) .forEach (key => {...
Will59
519
for (var k in target){
    if (target.hasOwnProperty(k)) {
         alert("Key is " + k + ", value is " + target[k]);
    }
}

hasOwnPropertysłuży do sprawdzania, czy targetnaprawdę ma tę właściwość, zamiast dziedziczenia jej po prototypie. Nieco prostsze byłoby:

for (var k in target){
    if (typeof target[k] !== 'function') {
         alert("Key is " + k + ", value is" + target[k]);
    }
}

To sprawdza tylko, że knie jest to metoda (jakby targetto arraydostaniesz wiele metod powiadamiani, np indexOf, push, popitp.)

J0HN
źródło
87
Innym sposobem na iterację tylko nad „własnymi” właściwościami jest Object.keys. Object.keys(target).forEach(function (key) { target[key]; });.
katspaugh
3
nie będzie działać, jeśli targetzostanie utworzony za pomocą Object.create(null), kod powinien zostać zmieniony target.hasOwnProperty(k)->Object.prototype.hasOwnProperty.call(target,k)
Azder
dlaczego nie użyć zmiennych podanych w przykładzie pytania? Co tu jest k, targeti property? Dla mnie nie-javascripter ten obszar nieokreślony :)
Gediminas
2
Object.keys (target) .forEach ((key) => {target [key];}); dla Angular
askilondz
315

Nikt o tym nie wspominał, Object.keyswięc wspomnę o tym.

Object.keys(obj).forEach(function (key) {
   // do something with obj[key]
});
kozioł
źródło
3
Uwaga: Nieobsługiwany przez IE8 i poniżej.
Edwin Stoteler,
1
W tym momencie powinieneś używać podkładki ES5. Jeśli mieszkasz w ładnej przyszłości ES6, użyj for of tc39wiki.calculist.org/es6/for-of
goatslacker
17
Warto zauważyć, że „Nie ma innego sposobu na zatrzymanie lub zerwanie pętli forEach () niż zgłoszenie wyjątku”
rluks,
Object.keys (obj) .forEach ((key) => {}); dla
Angulara
Nie działa na ES6 lub nie rozumiem tego. Felix ma lepszą i bardziej czytelną odpowiedź poniżej: data.forEach (funkcja (wartość, indeks) {console.log (indeks); // 0, 1, 2 ...});
gtamborero
115

bo ... w zadziała dla ciebie.

for( var key in obj ) {
  var value = obj[key];
}

W nowoczesnym JavaScript możesz również to zrobić:

for ( const [key,value] of Object.entries( obj ) ) {

}
Paweł
źródło
64
var obj = {...};
for (var key in obj) {
    var value = obj[key];

}

Składnia php to tylko cukier.

Zirak
źródło
Spowoduje to również iterację wszystkich odziedziczonych właściwości. Aby tego uniknąć, użyj .hasOwnProperty ().
LSerni,
24

Zakładam, że wiesz, że ito jest klucz i że możesz uzyskać wartość za pośrednictwem data[i](i po prostu chcę do tego skrótu).

ECMAScript5 wprowadził forEach [MDN] dla tablic (wygląda na to, że masz tablicę):

data.forEach(function(value, index) {

});

Dokumentacja MDN zawiera podkładkę dla przeglądarek, które jej nie obsługują.

Oczywiście nie działa to w przypadku obiektów, ale możesz utworzyć dla nich podobną funkcję:

function forEach(object, callback) {
    for(var prop in object) {
        if(object.hasOwnProperty(prop)) {
            callback(prop, object[prop]);
        }
    }
}

Ponieważ otagowałeś pytanie , jQuery zapewnia $.each [dokumentację], która zapętla zarówno struktury tablicowe, jak i obiektowe.

Felix Kling
źródło
To jest tablica forEach, a nie obiekt forEach.
2
Więc? Najwyraźniej OP zapętla się nad tablicą.
Felix Kling
Również Mozilla (Firefox, SpiderMonkey-C, Rhino i c) ma niestandardowe rozszerzenie, które umożliwia for eachskładnię. for each (let val in myObj) console.log(val);.
katspaugh
2
@katspaugh: Racja, ale ponieważ jest to tylko Mozilla, nie wydaje się bardzo przydatna.
Felix Kling
Wielkie dzięki za odpowiedź. Przeczytam podane informacje. Twoje założenie na początku odpowiedzi było słuszne, wiedziałem o tym, z tym wyjątkiem, że tak bardzo mi się podobało w tym projekcie, że nie mogę się skupić i zapomniałem o tym .. Dziękuję.
kabaret
10

Możesz do tego użyć for..in.

for (var key in data)
{
    var value = data[key];
}
Christoph Winkler
źródło
9
for (var key in myMap) {
    if (myMap.hasOwnProperty(key)) {
        console.log("key =" + key);
        console.log("value =" + myMap[key]);
    }
}

W javascript każdy obiekt ma kilka wbudowanych par klucz-wartość, które mają meta-informacje. Kiedy przechodzisz przez wszystkie pary klucz-wartość dla obiektu, również je przechodzisz. Zastosowanie hasOwnProperty () odfiltrowuje je.

Siddhu
źródło
2

ES6 dostarczy Map.prototype.forEach (callback), którego można użyć w ten sposób

myMap.forEach(function(value, key, myMap) {
                        // Do something
                    });
Stephen Murby
źródło
2
jaki jest parametr myMap?
phil294
Mapa nie jest obiektem. Są to całkowicie odrębne rzeczy.
Dakusan,
2
Funkcja forEach nie zawiera „klucza” tablicy, a bardziej indeks elementu, który aktualnie iterujesz.
Francis Malloch,
2
let test = {a: 1, b: 2, c: 3};
Object.entries(test).forEach(([key, value]) => console.log(key, value))

// a 1
// b 2
// c 3
吴毅 凡
źródło
5
Możesz dodać wyjaśnienie do opublikowanego kodu zamiast zwykłego kodu, który może nie być zrozumiały.
AaoIi
Object.entries wyciąga tablicy tablic na podstawie par klucz / wartość oryginalnego obiektu: [['a', 1],['b',2],['c',3]]. forEachDekonstruuje każdy z kluczowych tablic / wartość i ustawia dwie zmienne keyi value, aby być stosowane jako chcesz w funkcji - tu wydatek console.log.
Mark Swardstrom,
1

W tym celu możesz użyć pętli „for in”:

for (var key in bar) {
     var value = bar[key];
}
Richard Dalton
źródło
1

Poniżej znajduje się przykład, który jest tak blisko, jak to możliwe.

for(var key in data){
  var value = data[key];    
  //your processing here
}

Jeśli używasz jQuery, zobacz: http://api.jquery.com/jQuery.each/

Aidamina
źródło
1

Jeśli korzystasz z Lodash , możesz użyć_.forEach

_.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
  console.log(key + ": " + value);
});
// => Logs 'a: 1' then 'b: 2' (iteration order is not guaranteed).
Gil Epshtain
źródło
1

W ciągu ostatnich kilku lat, odkąd powstało to pytanie, Javascript dodał kilka nowych funkcji. Jednym z nich jest metoda Object.Entries .

Skopiowany bezpośrednio z MDN jest fragment kodu śledzenia


const object1 = {
  a: 'somestring',
  b: 42
};

for (let [key, value] of Object.entries(object1)) {
  console.log(`${key}: ${value}`);
}
David
źródło
-2

tak, możesz mieć tablice asocjacyjne również w javascript:

var obj = 
{
    name:'some name',
    otherProperty:'prop value',
    date: new Date()
};
for(i in obj)
{
    var propVal = obj[i]; // i is the key, and obj[i] is the value ...
}
Alex Pacurar
źródło
@PaulPRO ... wszystko w javascript jest parą klucz-wartość (a zatem obiekt jest w rzeczywistości tablicą asocjacyjną par klucz-wartość ...)
Alex Pacurar
@AlexPacurar i tablica asocjacyjna ma porządek. Obiekt jest nieuporządkowany. to duża różnica
Raynos
@Raynos możesz mieć rację ... to będzie wielka pomoc w wyjaśnieniu, w jaki sposób obiekt jest nieuporządkowany ... biorąc pod uwagę powyższy przykład, można by się spodziewać, że „i” w pętli for będzie [name, otherProperty, i na koniec data] ... więc w jakiej sytuacji kolejność właściwości obiektu będzie mieszana?
Alex Pacurar
@AlexPacurar określona kolejność, w jakiej będzie zapętlać obiekt, zależy od przeglądarki. Niektórzy robią to alfabetycznie, niektórzy robią to w kolejności definicji itp.
Raynos
3
@Raynos: Czy tablice asocjacyjne są koniecznie zamawiane? Często widziałem termin używany bardziej ogólnie. Na przykład w artykule Wikipedii na temat tablicy asocjacyjnej .
Jeremy Banks
-8
var global = (function() {
   return this;
})();

// Pair object, similar to Python

function Pair(key, value) {
    this.key = key;
    this.value = value;

    this.toString = function() {
       return "(" + key + ", " + value + ")";
    };
}

/**
 * as function
 * @param {String} dataName A String holding the name of your pairs list.
 * @return {Array:Pair} The data list filled
 *    with all pair objects.
 */
Object.prototype.as = function(dataName) {
    var value, key, data;
    global[dataName] = data = [];

    for (key in this) {
       if (this.hasOwnProperty(key)) {
          value = this[key];

          (function() {
             var k = key,
                 v = value;

            data.push(new Pair(k, v));
          })();
       }
    }

    return data;
};

var d = {
   'one': 1,
   'two': 2
};

// Loop on your (key, list) pairs in this way
for (var i = 0, max = d.as("data").length; i < max; i += 1) {
   key = data[i].key;
   value = data[i].value;

   console.log("key: " + key + ", value: " + value);
}

// delete data when u've finished with it.
delete data;
użytkownik278064
źródło