Как выполнить цикл или перечислить объект JavaScript?

у меня есть объект JavaScript, как показано ниже:

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

теперь я хочу, чтобы перебрать все p элементов (p1, p2, p3...) И получить свои ключи и значения. Как я могу это сделать?

при необходимости я могу изменить объект JavaScript. Моя конечная цель-перебрать несколько пар ключевых значений, и если возможно, я хочу избежать использования eval.

30 ответов


можно использовать for-in цикл, как показано другими. Однако вы также должны убедиться, что ключ, который вы получаете, является фактическим свойством объекта и не исходит из прототипа.

вот этот фрагмент:

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

for (var key in p) {
    if (p.hasOwnProperty(key)) {
        console.log(key + " -> " + p[key]);
    }
}

в ECMAScript 5 Вы можете объединить Object.keys() и Array.prototype.forEach():

var obj = { first: "John", last: "Doe" };

Object.keys(obj).forEach(function(key) {
    console.log(key, obj[key]);
});

на ES6 добавляет for...of:

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

ES2017 добавляет Object.entries() что избавляет от необходимости искать каждое значение в исходном объекте:

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

и Object.keys() и Object.entries() повторять свойства в том же порядке, что и for...in цикл но игнорируйте цепочку прототипов. Только собственный объект перечисляемые свойства повторяются.

Edit: ES2016 → ES6


вы должны использовать for-in loop

но будьте очень осторожны при использовании такого цикла, потому что это будет цикл всех свойств по цепочке прототипов.

поэтому при использовании циклов for-in всегда используйте hasOwnProperty метод, чтобы определить, является ли текущее свойство в итерации действительно свойством объекта, который вы проверяете:

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
}

вопрос не будет полным, если мы не упомянем об альтернативных методах циклического прохождения объектов.

в настоящее время многие известные библиотеки JavaScript предоставляют свои собственные методы для итерации по коллекциям, т. е. над массивы, объекты и массив-как объекты. Эти методы удобны в использовании и полностью совместимый с любым браузером.

  1. если вы работаете с jQuery, вы можете использовать jQuery.each() метод. Его можно использовать для плавного перебора как объектов, так и массивов:

    $.each(obj, function(key, value) {
        console.log(key, value);
    });
    
  2. на подчеркивания.js вы можете найти способ _.each(), который перебирает список элементов, получая каждый по очереди предоставленной функции (обратите внимание на порядок аргументов в iteratee функция!):

    _.each(obj, function(value, key) {
        console.log(key, value);
    });
    
  3. Lo-Dash предоставляет несколько методов для итерации по свойствам объекта. Basic _.forEach() (или это псевдоним _.each()) полезен для зацикливания как объектов, так и массивов, однако (!) объекты с length свойства обрабатываются как массивы, и во избежание такого поведения рекомендуется использовать _.forIn() и _.forOwn() методы (они также имеют


в ECMAScript 5 у вас есть новый подход в итерационных полях литерала -Object.keys

больше информации вы можете увидеть на MDN

мой выбор ниже, как более быстрое решение в текущих версиях браузеров (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;
}

вы можете сравнить производительность этого подхода с различными реализациями на jsperf.com:

поддержка браузера вы можете увидеть на таблица compat Кангакса

для старого браузера у вас есть простой и полное polyfill

UPD:

сравнение производительности для всех наиболее популярных случаев в этом вопросе на perfjs.info:

итерация объектного литерала


вы можете просто повторить его, как:

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

отметим, что key не будет принимать значение свойства, это просто значение индекса.


поскольку es2015 становится все более популярным, я публикую этот ответ, который включает использование генератора и итератора для плавной итерации [key, value] пар. Как это возможно на других языках, например Ruby.

Ok вот код:

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

вся информация о том, как вы можете сделать итератор и генератор вы можете найти на странице разработчика Mozilla.

надеюсь, что это помогло кому-то.

EDIT:

ES2017 будет включать Object.entries что сделает перебора [key, value] пары в объектах еще проще. Теперь известно, что он будет частью стандарта в соответствии с ts39 информация о сцене.

Я думаю, что пришло время обновить мой ответ, чтобы он стал еще более свежим, чем сейчас.

const MyObject = {
  'a': 'Hello',
  'b': 'it\'s',
  'c': 'me',
  'd': 'you',
  'e': 'looking',
  'f': 'for',
};

for (const [k, v] of Object.entries(MyObject)) {
  console.log(`Here is key ${k} and here is value ${v}`);
}

вы можете найти больше об использовании на MDN страница


предисловие:

  • свойства объекта могут быть собственные (свойство находится на самом объекте) или унаследовала (не на самом объекте, а на одном из его прототипов).
  • свойства объекта могут быть перечисли или неперечислимый. Не перечисляемые свойства остаются из множества перечислений свойств/массивов.
  • имена свойств могут быть строками или символами. Свойства, имена которых Символы остаются из множества перечислений/массивов свойств.

здесь в 2018 году, ваши варианты для перебора свойств объекта:

  1. for-in [ MDN, spec] - структура цикла, которая петляет по именам объекта перечисли свойства, включая унаследованные, имена которых являются строками
  2. Object.keys [MDN, spec] - функция, предоставляющая массив имен объекта собственные, перечисли свойства, имена которых являются строками.
  3. Object.values [MDN, spec] - функция, предоставляющая массив значения объекта собственные, перечисли свойства.
  4. Object.entries [ MDN, spec] - функция, предоставляющая массив имен и значения объекта собственные, перечисли свойства.
  5. Object.getOwnPropertyNames [MDN, spec] - функция, предоставляющая массив имен объекта собственные свойства (даже не перечисляемые), имена которых являются строками.
  6. Object.getOwnPropertySymbols [ MDN, spec] - функция, предоставляющая массив имен объекта собственные свойства (даже не перечисляемые), имена которых являются символами.
  7. Reflect.ownKeys [ MDN, spec] - функция, предоставляющая массив имен объекта собственные свойства (даже не перечисляемые), являются ли эти имена строками или символами.
  8. если вы хотите все объекта свойства, в том числе не перечисляемые унаследованные, необходимо использовать цикл и Object.getPrototypeOf [ MDN, spec] и использовать Object.getOwnPropertyNames, Object.getOwnPropertySymbols или Reflect.ownKeys для каждого объекта в цепочке прототипов (пример внизу этого ответа).

со всеми, кроме for-in, вы бы использовали какую-то конструкцию цикла в массиве (for, for-of, forEach, так далее.).

примеры:

for-in:

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const name in o) {
    const value = o[name];
    console.log(`${name} = ${value}`);
}

Object.keys for-of loop, но вы можете использовать любой цикл construct):

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const name of Object.keys(o)) {
    const value = o[name];
    console.log(`${name} = ${value}`);
}

Object.values:

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const value of Object.values(o)) {
    console.log(`${value}`);
}

Object.entries:

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const [name, value] of Object.entries(o)) {
    console.log(`${name} = ${value}`);
}

Object.getOwnPropertyNames:

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const name of Object.getOwnPropertyNames(o)) {
    const value = o[name];
    console.log(`${name} = ${value}`);
}

Object.getOwnPropertySymbols:

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const name of Object.getOwnPropertySymbols(o)) {
    const value = o[name];
    console.log(`${String(name)} = ${value}`);
}

Reflect.ownKeys:

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (const name of Reflect.ownKeys(o)) {
    const value = o[name];
    console.log(`${String(name)} = ${value}`);
}

все свойства, включая унаследованные не перечисляемые:

// A prototype object to inherit from, with a string-named property
const p = {answer: 42};
// The object we'll look at, which inherits from `p`
const o = Object.create(p);
// A string-named property
o.question = "Life, the Universe, and Everything";
// A symbol-named property
o[Symbol("author")] = "Douglas Adams";
for (let depth = 0, current = o; current; ++depth, current = Object.getPrototypeOf(current)) {
    for (const name of Reflect.ownKeys(current)) {
        const value = o[name];
        console.log(`[${depth}] ${String(name)} = ${String(value)}`);
    }
}
.as-console-wrapper {
  max-height: 100% !important;
}

via прототип С forEach () что должен пропустить прототип цепи свойства:

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

после просмотра всех ответов здесь, hasOwnProperty не требуется для моего собственного использования, потому что мой объект json чист; на самом деле нет смысла добавлять дополнительную обработку javascript. Это все, что я использую:

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

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

Примечание: Вы можете сделать это через массивы, но вы будете перебирать length и другие свойства тоже.


это интересные люди в этих ответах коснулись обоих Object.keys() и for...of но никогда не объединял их:

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

вы не можете просто for...of an Object потому что это не итератор, и for...index или .forEach()ing Object.keys() некрасиво и неэффективно.
Я рад, что большинство людей воздерживаются от for...in (с проверкой или без проверки .hasOwnProperty()) поскольку это также немного грязно, поэтому, кроме моего ответа выше, я здесь, чтобы сказать...


вы можете сделать обычные ассоциации объектов итерации! Ведет себя так же, как Maps с прямым использованием фантазии for...of
демо работа в Chrome и FF (я предполагаю только 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);

пока вы включаете мою прокладку ниже:

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

без необходимости создавать реальный объект карты, который не имеет хорошего синтаксического сахара.

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

на самом деле, с этой прокладкой, если вы все еще хотели воспользоваться другими функциями карты (без их перестановки), но все еще хотели использовать аккуратную нотацию объектов, поскольку объекты теперь итерабельны, теперь вы можете просто сделать карту из нее!

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

для тех, кто не любит ШИМ, или возиться с prototype в общем, не стесняйтесь делать функцию в окне вместо этого, называя ее чем-то вроде getObjIterator() затем;

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

теперь вы можете просто назвать его как обычная функция, ничто другое не влияет

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

или

for (let pair of getObjIterator(ordinaryObject))

нет причин, почему бы это не сработало.

Добро пожаловать в будущее.



вот еще один метод для итерации через объект.

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


Object.keys(p).forEach(key => { console.log(key, p[key]) })

на Object.keys() метод возвращает массив собственных перечисляемых свойств данного объекта. Подробнее об этом здесь

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

Object.keys(p).map((key)=> console.log(key + "->" + p[key]))

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>

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

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

для тех людей, которые не любят "for ... в"-способ:

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

Теперь, вы можете просто звоните:

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

Если вы не хотите получать конфликты с другими методами forEach, вы можете назвать его своим уникальным именем.


только код JavaScript без зависимостей:

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
}

петли могут быть довольно интересными при использовании чистого JavaScript. Похоже, что только ECMA6 (новая спецификация JavaScript 2015) получила циклы под контролем. К сожалению, когда я пишу это, как браузеры, так и популярная интегрированная среда разработки (IDE) все еще пытаются полностью поддерживать новые колокола и свистки.

на первый взгляд вот как выглядит цикл объектов JavaScript перед 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;
  }
}

кроме того, я знаю, что это выходит за рамки этой вопрос, но в 2011 году ECMAScript 5.1 добавил forEach метод только для массивов, который в основном создал новый улучшенный способ цикла через массивы, все еще оставляя не итерабельные объекты со старым многословным и запутанным for петли. Но странная часть в том, что это новое forEach метод не поддерживает break что привело ко всевозможным другим проблемам.

в основном в 2011 году нет реального твердого способа цикла в JavaScript, кроме того, что многие популярные библиотеки (jQuery, Подчеркивания и т. д.) решил переосмыслить.

по состоянию на 2015 год у нас теперь есть лучший способ зациклить (и сломать) любой тип объекта (включая массивы и строки). Вот как будет выглядеть цикл в JavaScript, когда рекомендация станет основной:

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

обратите внимание, что большинство браузеров не будут поддерживать код выше по состоянию на 18 июня 2016 года. Даже в Chrome вам нужно включить этот специальный флаг для его работы:chrome://flags/#enable-javascript-harmony

пока это не станет новый стандарт, старый метод все еще можно использовать, но есть и альтернативы в популярных библиотеках или даже легкий альтернатив для тех, кто не использует ни одну из этих библиотек.


Я бы сделал это вместо проверки obj.hasOwnerProperty внутри каждого for ... in петли.

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

Если вы хотите перебрать не перечисляемые свойства так же, вы можете использовать Object.getOwnPropertyNames(obj) для возврата массива всех свойств (перечисляемых или нет), найденных непосредственно на данном объекте.

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

Если кому-то нужно пройти через arrayObjects с условием:

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

рассматривая ES6, я хотел бы добавить свою собственную ложку сахара и предоставить еще один подход к итерации свойств объекта.

так как простой объект JS не типа Iterable просто из коробки, мы не можем использовать for..of цикл для итерации по его содержанию. Но нас никто не остановит!--15-->чтобы сделать его интерфейс Iterable.

давайте у нас есть


в последнем сценарии ES вы можете сделать что-то вроде этого:

Object.entries(p);

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

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

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

[...p] //["p1", "p2", "p3"]

это даст тот же результат, что и использование for...В цикле es6.

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

но важно знать возможности, которые вы теперь используете es6!


объект становится итератором, когда он реализует .метод next ()

const james = {
name: 'James',
height: `5'10"`,
weight: 185,

[Symbol.iterator]() {
let properties = []
for (let key of Object.keys(james)){
     properties.push(key);
 }

index = 0;
return {
        next: () => {
            let key = properties[index];
            let value = this[key];
            let done = index >= properties.length - 1 ;
            index++;
            return { key, value, done };
        }
    };
  }

};


const iterator = james[Symbol.iterator]();

console.log(iterator.next().value); // 'James'
console.log(iterator.next().value); // `5'10`
console.log(iterator.next().value); // 185

начиная с ES06 вы можете получить значения объекта в виде массива с помощью

let arrValues = Object.values( yourObject) ;

он возвращает массив значений объекта и не извлекает значения из прототипа!!

объект MDN DOCS.values ()

и для ключей (allready answerd передо мной здесь )

let arrKeys   = Object.keys(yourObject);

Если вы хотите перебирать только свойства, используйте один из ответов выше, однако, если вы хотите перебирать все, включая функции, то вы можете использовать


У меня была аналогичная проблема при использовании Angular, вот решение, которое я нашел.

Шаг 1. получить все ключи от объекта. используя объект.ключи. Этот метод возвращает массив собственных перечисляемых свойств данного объекта.

Шаг 2. создать пустой массив. Это где все свойства будут жить, так как ваш новый цикл ngFor будет указывать на этот массив, мы должны поймать их все. Шаг 3. итерации бросить все клавиши, и нажмите каждый из них в массив, который вы создали. Вот как это выглядит в коде.

    // Evil response in a variable. Here are all my vehicles.
let evilResponse = { 
  "car" : 
    { 
       "color" : "red",
       "model" : "2013"
    },
   "motorcycle": 
    { 
       "color" : "red",
       "model" : "2016"
    },
   "bicycle": 
    { 
       "color" : "red",
       "model" : "2011"
    }
}
// Step 1. Get all the object keys.
let evilResponseProps = Object.keys(evilResponse);
// Step 2. Create an empty array.
let goodResponse = [];
// Step 3. Iterate throw all keys.
for (prop of evilResponseProps) { 
    goodResponse.push(evilResponseProps[prop]);
}

вот ссылка на оригинальный пост. https://medium.com/@papaponmx/looping-over-object-properties-with-ngfor-in-angular-869cd7b2ddcc