For..In циклів у JavaScript - пари ключових значень


414

Мені було цікаво, чи є спосіб зробити щось на зразок foreachциклу PHP в JavaScript. Я шукаю функціональність приблизно на зразок цього фрагменту PHP:

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

Я дивився на for..inцикл JS , але, здається, немає способу вказати as. Якщо я це роблю з "нормальним" для циклу ( for(var i = 0; i < data.length; i++), чи є спосіб схопити ключ => пара значень?

Відповіді:


215

Якщо ви можете використовувати ES6 вдома або за допомогою Babel (js компілятор), ви можете зробити наступне:

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
Це працює ідеально, просто цікаво - порівняно з "для ключа в об'єкті, а потім отримати значення за об'єктом [ключ]", який з них дає кращі показники?
lsheng

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і т.д.) .


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 це область невизначеного :)
Gediminas

2
Object.keys (target) .forEach ((key) => {target [key];}); для Angular
askilondz

315

Ніхто не згадав, Object.keysтому я це згадаю.

Object.keys(obj).forEach(function (key) {
   // do something with obj[key]
});

3
Примітка: Не підтримується IE8 та нижче.
Edwin Stoteler

1
У цей момент ви повинні використовувати прошивку ES5. Якщо ви живете в приємному майбутньому for of ES6,
goatslacker

17
Варто зазначити, що "Немає іншого способу зупинити або розірвати цикл forEach (), крім викидання виключення"
rluks

Object.keys (obj) .forEach ((ключ) => {}); для Angular
askilondz

Він не працює на ES6 або я його не розумію. Нижче у Фелікса є краща і читабельна відповідь: data.forEach (функція (значення, індекс) {console.log (індекс); // 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 - це просто цукор.


Це також повторить усі успадковані властивості. Щоб уникнути цього, використовуйте .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], які перетворюються на структури обох, масивів та об'єктів.


Це Array forEach, а не об’єкт forEach.

2
Тому? Мабуть, ОП перекидається на масив.
Фелікс Клінг

Також Mozilla (Firefox, SpiderMonkey-C, Rhino & c) має нестандартне розширення, яке дозволяє for eachсинтаксису. for each (let val in myObj) console.log(val);.
katspaugh

2
@katspaugh: Правильно, але оскільки це лише Mozilla, це здається не дуже корисним.
Фелікс Клінг

Дякую за вашу відповідь. Я прочитаю інформацію, яку ви надали. Ваше припущення на початку відповіді було правильним, я знав, що, за винятком того, що я настільки сильно на голові отримав цей проект, що не можу зосередитись і забув про нього .. Дякую.
кабаре


9
for (var key in myMap) {
    if (myMap.hasOwnProperty(key)) {
        console.log("key =" + key);
        console.log("value =" + myMap[key]);
    }
}

У JavaScript кожен об'єкт має купу вбудованих пар ключів-значень, які мають метаінформацію. Коли ви перебираєте всі пари ключових значень для об'єкта, ви також перебираєте їх. Використання hasOwnProperty () фільтрує їх.


2

ES6 надасть Map.prototype.forEach (зворотний виклик), який можна використовувати так

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.
Марк Swardstrom



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 - пара ключ-значення (таким чином, об’єкт насправді є асоціативним масивом пар ключ-значення ...)
Alex Pacurar

@AlexPacurar та асокативний масив має порядок. Об'єкт не упорядкований. ось велика різниця
Raynos

@Raynos ви можете мати рацію ... це буде чудовою допомогою пояснити, як саме об'єкт є не упорядкованим ... з огляду на наведений вище приклад, можна було б очікувати, що "i" в циклі for буде [ім'я, otherProperty, і нарешті дата] ... так у якій ситуації буде змішаний порядок властивостей об'єкта?
Алекс Пакурар

@AlexPacurar певний порядок, в якому він буде переходити через об'єкт, є специфічним для браузера. Деякі роблять це в алфавітному порядку, інші
впорядковують

3
@Raynos: Чи обов'язково впорядковані асоціативні масиви? Я часто бачив термін, що використовується в більш загальному вигляді. Наприклад, на статті асоціативного масиву Wikipedia .
Джеремі Бенкс

-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;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.