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?

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! =)


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.)


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

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 ) ) {

}

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

}

Składnia php to tylko cukier.


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.


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


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.


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

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

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


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).

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

-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 ...
}

@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;
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.