Итерация по свойствам объекта
var obj = {
name: "Simon",
age: "20",
clothing: {
style: "simple",
hipster: false
}
}
for(var propt in obj){
alert(propt + ': ' + obj[propt]);
}
Как работает переменная propt
представлять свойства объекта? Это не встроенный метод или свойство. Тогда почему он подходит к каждому свойству объекта?
33 ответа
Перебор свойств требует этого дополнительного hasOwnProperty
проверять:
for (var property in object) {
if (object.hasOwnProperty(property)) {
// do stuff
}
}
Это необходимо, потому что прототип объекта содержит дополнительные свойства для объекта, которые являются технически частью объекта. Эти дополнительные свойства унаследованы от базового класса объекта, но все еще являются свойствами object
,
hasOwnProperty
просто проверяет, является ли это свойство специфичным для этого класса, а не наследуемым от базового класса.
Начиная с JavaScript 1.8.5 вы можете использовать Object.keys(obj)
получить массив свойств, определенных для самого объекта (те, которые возвращают true для obj.hasOwnProperty(key)
).
Object.keys(obj).forEach(function(key,index) {
// key: the name of the object key
// index: the ordinal position of the key within the object
});
Это лучше (и более читабельно), чем использование цикла for-in.
Поддерживается в следующих браузерах:
- Firefox (Gecko): 4 (2,0)
- Хром: 5
- Internet Explorer: 9
Дополнительную информацию смотрите в справочнике Mozilla Developer Network Object.keys ().
Девочки и парни, мы находимся в 2017 году, и у нас не так много времени для набора текста... Итак, давайте сделаем этот крутой новый модный ECMAScript 2016:
Object.keys(obj).forEach(e => console.log(`key=${e} value=${obj[e]}`));
В следующих версиях ES вы можете использовать Object.entries
:
for (const [key, value] of Object.entries(obj)) { }
или же
Object.entries(obj).forEach(([key, value]) => ...)
Если вы просто хотите перебрать значения, используйте Object.values:
for (const value of Object.values(obj)) { }
или же
Object.values(obj).forEach(value => ...)
Это for...in statement
( MDN, спецификация ECMAScript).
Вы можете прочитать это как " ДЛЯ каждого свойства в obj
объект, присвойте каждое свойство переменной PROPT по очереди ".
Это просто for...in
петля. Проверьте документацию в Mozilla.
if(Object.keys(obj).length) {
Object.keys(obj).forEach(key => {
console.log("\n" + key + ": " + obj[key]);
});
}
// *** Explanation line by line ***
// Explaining the bellow line
// It checks if obj has at least one property. Here is how:
// Object.keys(obj) will return an array with all keys in obj.
// Keys are just the regular incremental numbers starting from 0.
// If there is no keys in obj, it will return empty array = []
// Then it will get its length. At this point, it checks:
// If it has at least one element, it means it's bigger than 0
// which evaluates to true and the bellow code will be executed.
// Else means it's length = 0 which evaluates to false
// NOTE: you can use Object.hasOwnProperty() instead of Object.keys(obj).length
if(Object.keys(obj).length) {
// Explaining the bellow line
// Just like in the previous line, this returns an array with
// all keys in obj (because if code execution got here, it means
// obj has keys.)
// Then just invoke built-in javascript forEach() to loop
// over each key in returned array and calls a call back function
// on each array element (key), using ES6 arrow function (=>)
// Or you can just use a normal function ((key) { blah blah }).
Object.keys(obj).forEach(key => {
// The bellow line prints out all keys with their
// respective value in obj.
// key comes from the returned array in Object.keys(obj)
// obj[key] returns the value of key in obj
console.log("\n" + key + ": " + obj[key]);
});
}
Если ваша среда поддерживает ES2017, я бы порекомендовал Object.entries:
Object.entries(obj).forEach(([key, value]) => {
console.log(`${key} ${value}`);
});
Как показано в документации Mozillas Object.entries():
Метод Object.entries () возвращает массив пар перечислимого свойства [key, value] собственного объекта данного объекта в том же порядке, что и в цикле for... in (отличие состоит в том, что цикл for-in перечисляет свойства в цепи прототипа).
По сути, с Object.entries мы можем отказаться от следующего дополнительного шага, который необходим для старшего цикла for... in:
// This step is not necessary with Object.entries
if (object.hasOwnProperty(property)) {
// do stuff
}
Ответ Доминика идеален, я просто предпочитаю делать так, потому что читать чище:
for (var property in object) {
if (!object.hasOwnProperty(property)) continue;
// Do stuff...
}
jquery позволяет вам сделать это сейчас:
$.each( obj, function( key, value ) {
alert( key + ": " + value );
});
Цикл for... in представляет каждое свойство объекта, поскольку оно похоже на цикл for. Вы определили propt в цикле for... in, выполнив:
for(var propt in obj){
alert(propt + ': ' + obj[propt]);
}
Цикл for... in перебирает перечисляемые свойства объекта. Независимо от того, какую переменную вы определяете или помещаете в цикл for... in, она изменяется каждый раз, когда переходит к следующему свойству, которое она выполняет. Переменная в цикле for... in перебирает ключи, но ее значение является значением ключа. Например:
for(var propt in obj) {
console.log(propt);//logs name
console.log(obj[propt]);//logs "Simon"
}
Вы можете увидеть, как переменная отличается от значения переменной. Напротив, цикл for... делает противоположное.
Надеюсь, это поможет.
let obj = {"a": 3, "b": 2, "6": "a"}
Object.keys(obj).map((item) => {console.log("item", obj[item])})
// a
// 3
// 2
Чтобы добавить использование ES2015 Reflect.ownKeys(obj)
а также перебирая свойства через итератор.
Например:
let obj = { a: 'Carrot', b: 'Potato', Car: { doors: 4 } };
может быть повторен
// logs each key
Reflect.ownKeys(obj).forEach(key => console.log(key));
Если вы хотите выполнить итерацию непосредственно над значениями ключей объекта, вы можете определить iterator
так же, как итераторы JavaScipts по умолчанию для строк, массивов, типизированных массивов, Map и Set.
JS попытается выполнить итерацию через свойство итератора по умолчанию, которое должно быть определено как Symbol.iterator
,
Если вы хотите иметь возможность перебирать все объекты, вы можете добавить его в качестве прототипа Object:
Object.prototype[Symbol.iterator] = function*() {
for(p of Reflect.ownKeys(this)){ yield this[p]; }
}
Это позволит вам перебирать значения объекта с помощью цикла for..., например:
for(val of obj) { console.log('Value is:' + val ) }
Внимание: на момент написания этого ответа (июнь 2018 г.) все другие браузеры, кроме IE, поддерживают генераторы и for...of
итерация через Symbol.iterator
Приведенные выше ответы немного раздражают, потому что они не объясняют, что вы делаете внутри цикла for после того, как убедитесь, что это объект: ВЫ НЕ ПОЛУЧАЕТЕ ЕГО ПРЯМО! На самом деле вы получили только КЛЮЧ, который вам нужен для подачи заявления в OBJ:
var obj = {
a: "foo",
b: "bar",
c: "foobar"
};
// We need to iterate the string keys (not the objects)
for(var someKey in obj)
{
// We check if this key exists in the obj
if (obj.hasOwnProperty(someKey))
{
// someKey is only the KEY (string)! Use it to get the obj:
var myActualPropFromObj = obj[someKey]; // Since dynamic, use [] since the key isn't literally named "someKey"
// NOW you can treat it like an obj
var shouldBeBar = myActualPropFromObj.b;
}
}
Это все безопасно ECMA5. Даже работает в хромых версиях JS, таких как Rhino;)
Вы можете получить доступ к вложенным свойствам объекта, используя
for...in
и
forEach
петля.
for...in
:
for (const key in info) {
consoled.log(info[key]);
}
forEach
:
Object.keys(info).forEach(function(prop) {
console.log(info[prop]);
// cities: Array[3], continent: "North America", images: Array[3], name: "Canada"
// "prop" is the property name
// "data[prop]" is the property value
});
Вы можете использовать Lodash. Документация
var obj = {a: 1, b: 2, c: 3};
_.keys(obj).forEach(function (key) {
...
});
Object.keys(obj).forEach(key =>
console.log(`key=${key} value=${obj[key]}`)
);
В настоящее время вы можете преобразовать стандартный объект JS в итерируемый объект, просто добавив метод Symbol.iterator. Тогда вы можете использовать for of
Цикл и принять его значения напрямую или даже может использовать оператор распространения на объекте тоже. Здорово. Давайте посмотрим, как мы можем это сделать:
var o = {a:1,b:2,c:3},
a = [];
o[Symbol.iterator] = function*(){
var ok = Object.keys(this);
i = 0;
while (i < ok.length) yield this[ok[i++]];
};
for (var value of o) console.log(value);
// or you can even do like
a = [...o];
console.log(a);
Ваш for
цикл перебирает все свойства объекта obj
, propt
определяется в первой строке вашего цикла for. Это строка, которая является именем свойства obj
объект. На первой итерации цикла propt
будет "имя".
Объекты в JavaScript являются коллекциями свойств и поэтому могут быть зациклены в каждом выражении.
Вы должны думать о obj
в качестве коллекции значения ключа.
Если работает Node, я бы порекомендовал:
Object.keys(obj).forEach((key, index) => {
console.log(key);
});
Хотя самый популярный ответ верен, вот альтернативный вариант использования, например, если вы выполняете итерацию по объекту и хотите в конце создать массив. Использовать.map
вместо того forEach
const newObj = Object.keys(obj).map(el => {
//ell will hold keys
// Getting the value of the keys should be as simple as obj[el]
})
Я хочу добавить к ответам выше, потому что у вас могут быть другие намерения от Javascript. Объект JSON и объект Javascript - это разные вещи, и вы можете захотеть пройтись по свойствам объекта JSON, используя решения, предложенные выше, а затем удивиться.
Предположим, что у вас есть объект JSON, такой как:
var example = {
"prop1": "value1",
"prop2": [ "value2_0", value2_1"],
"prop3": {
"prop3_1": "value3_1"
}
}
Неправильный способ перебора его "свойств":
function recursivelyIterateProperties(jsonObject) {
for (var prop in Object.keys(example)) {
console.log(prop);
recursivelyIterateProperties(jsonObject[prop]);
}
}
Вы можете быть удивлены, увидев запись консоли 0
, 1
и т. д. при переборе свойств prop1
а также prop2
и из prop3_1
, Эти объекты являются последовательностями, а индексы последовательности являются свойствами этого объекта в Javascript.
Лучший способ рекурсивно перебрать свойства объекта JSON - это сначала проверить, является ли этот объект последовательностью или нет:
function recursivelyIterateProperties(jsonObject) {
for (var prop in Object.keys(example)) {
console.log(prop);
if (!(typeof(jsonObject[prop]) === 'string')
&& !(jsonObject[prop] instanceof Array)) {
recursivelyIterateProperties(jsonObject[prop]);
}
}
}
Здесь я перебираю каждый узел и создаю значимые имена узлов. Если вы заметили, instanceOf Array и instanceOf Object в основном делают одно и то же (хотя в моем приложении я даю другую логику)
function iterate(obj,parent_node) {
parent_node = parent_node || '';
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
var node = parent_node + "/" + property;
if(obj[property] instanceof Array) {
//console.log('array: ' + node + ":" + obj[property]);
iterate(obj[property],node)
} else if(obj[property] instanceof Object){
//console.log('Object: ' + node + ":" + obj[property]);
iterate(obj[property],node)
}
else {
console.log(node + ":" + obj[property]);
}
}
}
}
примечание - меня вдохновляет ответ Ондрея Свейдара. Но это решение имеет лучшую производительность и менее неоднозначно
Также добавляем рекурсивный способ:
function iterate(obj) {
// watch for objects we've already iterated so we won't end in endless cycle
// for cases like var foo = {}; foo.bar = foo; iterate(foo);
var walked = [];
var stack = [{obj: obj, stack: ''}];
while(stack.length > 0)
{
var item = stack.pop();
var obj = item.obj;
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
if (typeof obj[property] == "object") {
// check if we haven't iterated through the reference yet
var alreadyFound = false;
for(var i = 0; i < walked.length; i++)
{
if (walked[i] === obj[property])
{
alreadyFound = true;
break;
}
}
// new object reference
if (!alreadyFound)
{
walked.push(obj[property]);
stack.push({obj: obj[property], stack: item.stack + '.' + property});
}
}
else
{
console.log(item.stack + '.' + property + "=" + obj[property]);
}
}
}
}
}
Использование:
iterate({ foo: "foo", bar: { foo: "foo"} });
По сути, вы хотите просмотреть каждое свойство объекта.
var Dictionary = {
If: {
you: {
can: '',
make: ''
},
sense: ''
},
of: {
the: {
sentence: {
it: '',
worked: ''
}
}
}
};
function Iterate(obj) {
for (prop in obj) {
if (obj.hasOwnProperty(prop) && isNaN(prop)) {
console.log(prop + ': ' + obj[prop]);
Iterate(obj[prop]);
}
}
}
Iterate(Dictionary);
Цикл for..in заключается в том, что он создает новую переменную (var someVariable) и затем сохраняет каждое свойство данного объекта в этой новой переменной (someVariable) по одному. Поэтому, если вы используете block {}, вы можете выполнить итерацию. Рассмотрим следующий пример.
var obj = {
name:'raman',
hobby:'coding',
planet:'earth'
};
for(var someVariable in obj) {
//do nothing..
}
console.log(someVariable); // outputs planet
Тип проверки
Вы можете проверить, как propt представляет свойства объекта,
typeof propt
чтобы обнаружить, что это всего лишь строка (имя свойства). Он связан с каждым свойством объекта из-за того, как for-in
js работает "встроенный" цикл.
var obj = {
name: "Simon",
age: "20",
clothing: {
style: "simple",
hipster: false
}
}
for(var propt in obj){
console.log(typeof propt, propt + ': ' + obj[propt]);
}
Проверьте эту ссылку, это поможет https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_state_forin
var person = {fname:"John", lname:"Doe", age:25};
var text = "";
var x;
for (x in person) {
text += person[x] + " "; // where x will be fname,lname,age
}
Console.log(text);
Для дальнейшего уточнения принятого ответа стоит отметить, что если вы создаете экземпляр объекта с помощью var object = Object.create(null)
затем object.hasOwnProperty(property)
вызовет ошибку TypeError. Поэтому, чтобы быть в безопасности, вам нужно вызвать его из прототипа так:
for (var property in object) {
if (Object.prototype.hasOwnProperty.call(object, property)) {
// do stuff
}
}