Циклы For..In в JavaScript - пары ключ-значение

414

Мне было интересно, есть ли способ сделать что-то вроде foreachцикла PHP в JavaScript. Функциональность, которую я ищу, выглядит примерно так: PHP Snippet:

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

Я смотрел на for..inцикл JS , но, похоже, нет способа указать as. Если я сделаю это с «нормальным» для цикла ( for(var i = 0; i < data.length; i++), есть ли способ получить пары ключ => значение?

кабаре
источник

Ответы:

217

Если вы можете использовать ES6 изначально или с Babel (js compiler), то вы можете сделать следующее:

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

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

Который распечатает этот вывод:

a 1
b 2
c 3

Object.entries()Метод возвращает массив собственного перечислимых свойств данного объекта [key, value]пара, в том же порядке , как это предусмотрено в for...inцикле ( с той разницей, что в течение цикла перебирает свойства в цепочке прототипов, а) .

Надеюсь, поможет! знак равно

Франческо Касула
источник
1
Это прекрасно работает, просто интересно - по сравнению с «для ключа в объекте, а затем получить значение по объекту [ключ]», который дает лучшую производительность?
Ишен
1
В этом конкретном случае я бы предположил, что это медленнее из-за Object.entriesвызова. Я не проводил никаких тестов, хотя.
Франческо
6
это лучший ответ на рассматриваемый вопрос, в котором задается вопрос о получении ключа и значения в цикле for.
Cipak
4
Принятый ответ должен быть обновлен, поскольку это фактически отвечает на вопрос, хотя он не был доступен на момент вопроса.
Марк Квали
1
Возможно, вы захотите проверить этот вопрос: stackoverflow.com/questions/47213651/…, который, кажется, указывает на то, что рекомендуется использовать синтаксис этого типа: Object.keys (myObject) .forEach (key => {...
Will59
519
for (var k in target){
    if (target.hasOwnProperty(k)) {
         alert("Key is " + k + ", value is " + target[k]);
    }
}

hasOwnPropertyиспользуется, чтобы проверить, targetдействительно ли у вас есть это свойство, а не унаследовано от его прототипа. Немного проще было бы:

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

Он просто проверяет , что kэто не метод (как будто targetэто arrayвы получите много способов оповещения, например indexOf, push, popи т.д.) .

J0HN
источник
87
Еще один способ перебора только «собственных» свойств Object.keys. Object.keys(target).forEach(function (key) { target[key]; });,
katspaugh
3
не будет работать, если targetсоздан с использованием Object.create(null), код должен быть изменен target.hasOwnProperty(k)->Object.prototype.hasOwnProperty.call(target,k)
Azder
почему бы не использовать переменные, приведенные в примере вопроса? Что здесь есть k, targetа property? Для меня не javascripter эта область неопределена :)
Гедиминас
2
Object.keys (target) .forEach ((key) => {target [key];}); для Angular
Аскилондз
315

Никто не упомянул, Object.keysпоэтому я упомяну это.

Object.keys(obj).forEach(function (key) {
   // do something with obj[key]
});
goatslacker
источник
3
Примечание: не поддерживается IE8 и ниже.
Эдвин Стотелер
1
На этом этапе вы должны использовать прокладку ES5. Если вы живете в прекрасном будущем for of ES6,
goatslacker
17
Стоит отметить, что «Нет способа остановить или прервать цикл forEach (), кроме как с помощью исключения»
rluks
Object.keys (obj) .forEach ((key) => {}); для Angular
Askilondz
Это не работает на ES6, или я не понимаю этого. У Феликса есть лучший и более читаемый ответ ниже: data.forEach (function (value, index) {console.log (index); // 0, 1, 2 ...});
gtamborero
115

для ... в будет работать для вас.

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

В современном JavaScript вы также можете сделать это:

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

}
Павел
источник
64
var obj = {...};
for (var key in obj) {
    var value = obj[key];

}

Синтаксис PHP просто сахар.

Zirak
источник
Это также будет повторять все унаследованные свойства. Чтобы избежать этого, используйте .hasOwnProperty ().
LSerni
24

Я предполагаю, что вы знаете, что iэто ключ и что вы можете получить значение через data[i](и просто хотите ярлык для этого).

ECMAScript5 представил forEach [MDN] для массивов (кажется, у вас есть массив):

data.forEach(function(value, index) {

});

Документация по MDN предоставляет оболочку для браузеров, которые ее не поддерживают.

Конечно, это не работает для объектов, но вы можете создать аналогичную функцию для них:

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

Поскольку вы пометили вопрос jQuery предоставляет $.each [docs], который перебирает структуры массива и объекта.

Феликс Клинг
источник
Это массив forEach, а не объект forEach.
2
Так? По-видимому, OP зацикливается на массиве.
Феликс Клинг
Также Mozilla (Firefox, SpiderMonkey-C, Rhino & c) имеет нестандартное расширение, которое допускает for eachсинтаксис. for each (let val in myObj) console.log(val);,
katspaugh
2
@katspaugh: Верно, но поскольку это только Mozilla, это не кажется очень полезным.
Феликс Клинг
Большое спасибо за ваш ответ. Я прочитаю информацию, которую вы предоставили. Ваше предположение в начале ответа было верным, я знал, что, за исключением того, что я получил так много от этого проекта, что не могу сосредоточиться и забыл об этом .. Спасибо.
кабаре
10

Вы можете использовать for..inдля этого.

for (var key in data)
{
    var value = data[key];
}
Кристоф Винклер
источник
9
for (var key in myMap) {
    if (myMap.hasOwnProperty(key)) {
        console.log("key =" + key);
        console.log("value =" + myMap[key]);
    }
}

В javascript каждый объект имеет набор встроенных пар ключ-значение, которые имеют метаинформацию. Когда вы перебираете все пары ключ-значение для объекта, вы также перебираете их. Использование hasOwnProperty () отфильтровывает их.

Siddhu
источник
2

ES6 предоставит Map.prototype.forEach (callback), который можно использовать следующим образом

myMap.forEach(function(value, key, myMap) {
                        // Do something
                    });
Стивен Мерби
источник
2
для чего этот параметр myMap?
phil294
Карта не является объектом. Это совершенно разные вещи.
Дакусан
2
Функция forEach содержит не «ключ» массива, а скорее индекс элемента, который вы сейчас перебираете.
Фрэнсис Маллок
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
Вы можете добавить некоторые объяснения с кодом, который вы разместили, вместо публикации простого кода, который может быть непонятным.
AaoIi
Object.entries вытаскивает массив массивов на основе пар ключ / значение исходного объекта: [['a', 1],['b',2],['c',3]]. forEachРазбирает каждое из ключевых значений массивов / и устанавливает две переменные keyи value, чтобы использовать , как вы хотите , чтобы функция - здесь выход в console.log.
Марк Свардстрем
1

Вы можете использовать цикл for для этого:

for (var key in bar) {
     var value = bar[key];
}
Ричард Далтон
источник
1

Ниже приведен пример, который подходит как можно ближе.

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

Если вы используете jQuery, смотрите: http://api.jquery.com/jQuery.each/

Aidamina
источник
1

Если вы используете Lodash , вы можете использовать_.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

За последние несколько лет, с тех пор как был задан этот вопрос, Javascript добавил несколько новых функций. Одним из них является метод Object.Entries .

Скопирован непосредственно из MDN, следующий фрагмент кода


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

for (let [key, value] of Object.entries(object1)) {
  console.log(`${key}: ${value}`);
}
Дэвид
источник
-2

да, вы можете иметь ассоциативные массивы также в 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 ... все в javascript - это пара ключ-значение (таким образом, объект на самом деле является ассоциативным массивом пар ключ-значение ...)
Алекс Пакурар
@AlexPacurar и ассоциативный массив имеют порядок. Объект неупорядочен. то будет большая разница
Raynos
@Raynos вы можете быть правы ... это будет большая помощь, чтобы объяснить, как именно неупорядоченный объект ... учитывая приведенный выше пример, можно ожидать, что 'i' в цикле for будет [name, otherProperty, и, наконец, дата] ... так в какой ситуации порядок свойств объекта будет смешанным?
Алекс Пакурар
@AlexPacurar конкретный порядок, в котором он будет зацикливаться на объекте, зависит от браузера. Некоторые делают это в алфавитном порядке, некоторые делают это в порядке определения и т. Д.
Raynos
3
@Raynos: обязательно ли упорядочивать ассоциативные массивы? Я часто видел термин, используемый более широко. Например, о ассоциативном массиве статьи в Википедии .
Джереми Бэнкс
-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;
user278064
источник