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


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

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

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

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

30 2221

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() повторите свойства в том же порядке, что и A 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 предоставляет несколько методов для итерации по свойствам объекта. Основные _.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:

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

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

UPD:

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

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

Вы можете просто перебрать его как:

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

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

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

ОК, Вот код:

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.keysfor-of цикл, но вы можете использовать любой цикл строительство):

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

через прототип С 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()ное Object.keys() некрасиво и неэффективно.
Я рад, что большинство людей воздерживаются от for...in (с проверкой или без проверки .hasOwnProperty()) так как это тоже немного грязно, поэтому, кроме моего ответа выше, я здесь, чтобы сказать...


вы можете сделать обычные ассоциации объектов итерации! Ведет себя так же, как Map s с прямым использованием фантазии 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]);

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

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

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

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

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 цикл для итерации по его содержанию. Но никто не может остановить нас чтобы сделать его 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...in петля 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