Как выполнить итерацию по вложенному циклу и получить доступ к определенному свойству? [Дубликат]

Существует плагин, который расширяет CSS, чтобы включить некоторые нестандартные функции, которые действительно могут помочь при разработке веб-сайтов. Он называется EQCSS .

Одна из вещей, которые добавляет EQCSS, является родительским селектором. Он работает во всех браузерах IE8 и выше. Вот формат:

@element 'a.active' {
  $parent {
    background: red;
  }
}

Итак, здесь мы открыли запрос элемента для каждого элемента a.active, а для стилей внутри этого запроса такие вещи, как $parent, имеют смысл, потому что есть контрольная точка , Браузер может найти родителя, потому что он очень похож на parentNode в JavaScript.

Вот демонстрация $parent и еще одной демонстрации $parent, которая работает в IE8 , а также снимок экрана, если у вас нет IE8 для тестирования с помощью .

EQCSS также включает в себя метаселектора $prev для элемента перед выбранным элементом, $this только для тех элементов, которые соответствуют запросу элемента, и многое другое.

1576
задан Rafay 1 November 2016 в 15:04
поделиться

24 ответа

Ваш цикл for выполняет итерацию по всем свойствам объекта obj. propt определяется в первой строке цикла for. Это строка, которая является именем свойства объекта obj. На первой итерации цикла propt будет «name».

6
ответ дан arb 19 August 2018 в 14:29
поделиться

Ответ Dominik's идеален, я просто предпочитаю делать это так, как это чище читать:

for (var property in object) {
    if (!object.hasOwnProperty(property)) continue;

    // Do stuff...
}
12
ответ дан Cyril N. 19 August 2018 в 14:29
поделиться

Это for...in statement ( MDN , ECMAScript spec ).

Вы можете прочитать это как «ДЛЯ каждого свойства IN obj объект, каждый раз присваивает каждое свойство переменной PROPT ".

191
ответ дан Dan Dascalescu 19 August 2018 в 14:29
поделиться
  • 1
    Согласитесь с @RightSaidFred, оператор in и оператор for вообще не участвуют, инструкция for-in представляет собой произведение грамматики сама по себе: for ( LeftHandSideExpression in Expression ), for ( var VariableDeclarationNoIn in Expression ) – CMS 29 November 2011 в 17:08
  • 2
    Странно, что в этом ответе так много голосов, тем более, что эти популярные комментарии, похоже, противоречат ему. – Doug Molineux 22 August 2013 в 22:46
  • 3
    Почему это обозначено как ответ? Это, пожалуй, наименее полезно в этой теме. – computrius 12 December 2013 в 19:48
  • 4
    @PeteHerbertPenito, странно, что никто не потрудился отредактировать ответ, пока не сделал . – Dan Dascalescu 17 April 2014 в 09:09
  • 5
    Наименее полезный ответ? Зависит от того, что вы думаете, о котором спрашивал ОП; когда я впервые прочитал вопрос, казалось, что это путаное смешение в отношении механизма, посредством которого переменная может использоваться для проверки свойств объекта и который этот ответ объясняет красноречиво (несмотря на то, , Вопрос «Почему он возникает с каждым свойством»? Я вижу, это может означать, что OP ищет hasOwnProperty, но не знает этого, но я думаю, что более вероятно, что этот был тем, что OP хотел знать, и неправильно принял правильный ответ на другой вопрос , :-) – Bumpy 21 September 2016 в 09:13

Чтобы добавить 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 будет пытаться выполнить итерацию с использованием свойства iterator по умолчанию, которое должно быть определено как Symbol.iterator.

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

Object.prototype[Symbol.iterator] = function*() { 
    for(p of Reflect.ownKeys(this)){ yield this[p]; }
}

Это позволит вам выполнять итерацию по значениям объекта с помощью цикла for for ..., например:

for(val of obj) { console.log('Value is:' + val ) }

Внимание: в качестве написав этот ответ (июнь 2018 г.) обо всех других браузерах, но IE, генераторы поддержки и for...of итерации через Symbol.iterator

0
ответ дан Dimitar Nikovski 19 August 2018 в 14:29
поделиться

Вышеупомянутые ответы немного раздражают, потому что они не объясняют, что вы делаете внутри цикла 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;)

12
ответ дан Dylan Hunt 19 August 2018 в 14:29
поделиться

Здесь я повторяю каждый узел и создаю значимые имена узлов. Если вы заметили, 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]);
            }
        }
    }
}

note - Я вдохновлен ответом Ondrej Svejdar. Но это решение имеет лучшую производительность и менее двусмысленный

2
ответ дан Faiz Mohamed Haneef 19 August 2018 в 14:29
поделиться
Object.keys(obj).forEach(key =>
  console.log(`key=${key} value=${obj[key]}`)
);
6
ответ дан Fellow Stranger 19 August 2018 в 14:29
поделиться

Девочки и ребята, мы в 2017 году, и у нас нет такого количества времени для набора текста ... Итак, давайте сделаем этот новый классный ECMAScript 2016:

Object.keys(obj).forEach(e => console.log(`key=${e}  value=${obj[e]}`));
146
ответ дан Frank Roth 19 August 2018 в 14:29
поделиться
  • 1
    Как это отличается от ответа Дэнни Р? – krillgar 11 January 2017 в 16:37
  • 2
    Это один лайнер и используйте карту вместо forEach. А также заявление console.log может быть интересным для некоторых людей. – Frank Roth 12 January 2017 в 17:08
  • 3
    Если вы не скопировали этот фрагмент напрямую и задаетесь вопросом, почему ваше сообщение журнала консоли обрабатывается как строка, не забудьте использовать обратные элементы (`) вместо одиночных кавычек (') xD – kayleeFrye_onDeck 19 April 2017 в 18:58
  • 4
    Если вы хотите сохранить еще 2 символа, вы можете избавиться от () вокруг аргумента e ... Object.keys(obj).map(e => console.log(`key=${e} value=${obj[e]}`)) – Grant 3 May 2017 в 02:39
  • 5
    – developerbmw 30 September 2017 в 01:33
  • 6
    forEach здесь более уместно. map() более подходит, если вы хотите преобразовать данные и использовать значение, возвращаемое функцией map(). Когда вы используете forEach, вы явно указываете, что выполняете только итерации для побочных эффектов, а не для преобразования. – Ski 31 October 2017 в 13:52

Вы в основном хотите перебирать каждое свойство в объекте.

JSFiddle

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);
2
ответ дан HovyTech 19 August 2018 в 14:29
поделиться
  • 1
    obj(prop) & lt; - TypeError: obj не является функцией – le_m 23 June 2016 в 21:31
  • 2
    @le_m мой плохой. Я должен случайно извлечь атрибут hasOwnProperty. Теперь он должен работать. – HovyTech 23 June 2016 в 22:29

Я хочу добавить к ответам выше, потому что у вас могут быть разные намерения от 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]);

            }

     }
}
2
ответ дан Jadiel de Armas 19 August 2018 в 14:29
поделиться

Итерация по свойствам требует этой дополнительной проверки hasOwnProperty:

for (var property in object) {
    if (object.hasOwnProperty(property)) {
        // do stuff
    }
}

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

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

2061
ответ дан Jens 19 August 2018 в 14:29
поделиться
  • 1
    @BT Согласно документации Mozilla : «Если вы хотите только учитывать свойства, связанные с самим объектом, а не его прототипы, используйте getOwnPropertyNames или выполните проверку hasOwnProperty ( свойствоIsEnumerable также можно использовать). & quot; – davidmdem 6 August 2013 в 20:47
  • 2
    Какова именно точка вызова object.hasOwnProperty()? Разве тот факт, что property имеет какое-либо значение, означает, что его в object? – Alex S 21 April 2014 в 20:48
  • 3
    Поскольку, Alex S, прототип объекта содержит дополнительные свойства для объекта, которые являются технически частью объекта. Они наследуются от базового класса объектов, но они все еще являются свойствами. hasOwnProperty просто проверяет, является ли это свойством, специфичным для этого класса, а не унаследованным от базового класса. Хорошее объяснение: brianflove.com/2013/09/05/javascripts-hasownproperty-method – Kyle Richter 28 April 2014 в 21:02
  • 4
    Я чувствую, что я должен упомянуть, однако, что Object.keys (obj) теперь намного лучшее решение для получения ключей самого объекта. Ссылка на документацию Mozilla: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… – Kyle Richter 28 April 2014 в 21:07
  • 5
    Отсутствует одна важная часть информации. property является строкой здесь, ее нужно было бы назвать propertyName. В противном случае может возникнуть путаница для новичков JS, таких как я, т. Е. Что делать внутри if. – Neolisk 20 July 2016 в 15:57

Если ваша среда поддерживает ES2017, я бы рекомендовал Object.entries:

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

Как показано в документации Mozillas Object.entries () :

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

В основном с Object.entries мы можем отказаться от следующего дополнительного шага, который требуется для более старого для ... in loop:

// This step is not necessary with Object.entries
if (object.hasOwnProperty(property)) {
  // do stuff
}
11
ответ дан JSON C11 19 August 2018 в 14:29
поделиться

Если вы используете Node, я бы рекомендовал:

Object.keys(obj).forEach((key, index) => {
    console.log(key);
});
3
ответ дан Justin 19 August 2018 в 14:29
поделиться

Чтобы уточнить принятый ответ, стоит отметить, что если вы создаете экземпляр объекта с помощью var object = Object.create(null), тогда object.hasOwnProperty(property) вызовет TypeError. Чтобы быть в безопасности, вам нужно вызвать его из прототипа следующим образом:

for (var property in object) {
    if (Object.prototype.hasOwnProperty.call(object, property)) {
        // do stuff
    }
}
1
ответ дан Konrad Kiss 19 August 2018 в 14:29
поделиться

Это всего лишь цикл for...in. Проверьте документацию в Mozilla .

37
ответ дан Matt Ball 19 August 2018 в 14:29
поделиться
  • 1
    это довольно основное различие, а не само по себе достойное достоинства, которое вы назначили. Это плохо написанный ответ, в котором отсутствует контекст и приложение к исходному вопросу. – FlavorScape 20 March 2014 в 23:33
  • 2
    Этот ответ по-прежнему намного лучше, чем большинство ответов, которые полностью не могут решить этот вопрос. – developerbmw 30 September 2017 в 01:58

Также добавление рекурсивного пути:

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"} }); 
4
ответ дан Ondrej Svejdar 19 August 2018 в 14:29
поделиться
  • 1
    не могли бы вы объяснить логику «уже основаны» – Faiz Mohamed Haneef 21 February 2016 в 16:55
  • 2
    @faiz - см. мои комментарии, это защита от застревания в бесконечном цикле, когда вы периодически проходите через объект, имеющий циклические ссылки – Ondrej Svejdar 22 February 2016 в 09:36
  • 3
    ОК. проверьте мой ниже soln. благодаря – Faiz Mohamed Haneef 22 February 2016 в 11:21

Вы можете использовать Lodash. Документация

var obj = {a: 1, b: 2, c: 3};
_.keys(obj).forEach(function (key) {
    ...
});
10
ответ дан Paul Rooney 19 August 2018 в 14:29
поделиться
  • 1
    Почему на самом деле этот «ответ» есть 10 upvotes? Он полностью не отвечает на вопрос. Я начинаю терять веру в интеллект в среднем разработчике JS. – developerbmw 30 September 2017 в 01:53
  • 2
    @developerbmw Я понимаю, что использование функций ES6 является более правильным, но я ответил год назад. Пожалуйста, поделитесь своими мыслями с нами, когда у вас есть минута. – viktarpunko 2 October 2017 в 08:20
  • 3
    Идея состоит в том, чтобы больше сосредоточиться на собственных методах, вместо того, чтобы предлагать пользователю добавить 10000-строчную библиотеку на свою страницу. Не поймите меня неправильно, мне нравится использовать Lodash, но есть время и место для этого, и это не так. – Will Hoskings 19 June 2018 в 19:58
let obj = {"a": 3, "b": 2, "6": "a"}

Object.keys(obj).map((item) => {console.log("item", obj[item])})

// a
// 3
// 2
10
ответ дан Philll_t 19 August 2018 в 14:29
поделиться

Что для цикла ... в том, что он создает новую переменную (var someVariable), а затем сохраняет каждое свойство данного объекта в этой новой переменной (someVariable) один за другим. Поэтому, если вы используете block {}, вы можете выполнять итерацию. Рассмотрим следующий пример.

var obj = {
     name:'raman',
     hobby:'coding',
     planet:'earth'
     };

for(var someVariable in obj) {
  //do nothing..
}

console.log(someVariable); // outputs planet
0
ответ дан Raman Sohi 19 August 2018 в 14:29
поделиться
  • 1
    Активировать это, учитывая его простоту. В моем случае я должен проверить все атрибуты в объекте на изворотливые значения - NaNs, nulls, undefined (они были точками на графике, и эти значения не позволяют графику рисовать). Чтобы получить значение вместо имени, в цикле вы просто выполните obj[someVariable]. Возможно, причина, по которой она была занижена, - это потому, что она не рекурсивна. Таким образом, это не будет адекватным решением, если у вас есть структурированный объект. – Katharine Osborne 27 April 2018 в 09:50

В настоящее время вы можете преобразовать стандартный объект 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);

8
ответ дан Redu 19 August 2018 в 14:29
поделиться
  • 1
    Интересный способ сделать это. Спасибо за открытие function*! – Benj 27 January 2017 в 11:22

jquery позволяет сделать это сейчас:

$.each( obj, function( key, value ) {
  alert( key + ": " + value );
});
20
ответ дан Rob Sedgwick 19 August 2018 в 14:29
поделиться
  • 1
    $.each({foo:1, length:0, bar:2}, function(k,v){console.log(k,v)}) $ .each не подходит для объектов. Если объект имеет свойство length, а его значение равно нулю, весь объект обрабатывается так, как если бы он был пустым массивом. – Bob Stein 4 April 2018 в 12:25
  • 2
    Подробности , почему я думаю, что это привлекательный для ошибок подход . – Bob Stein 4 April 2018 в 14:43

Начиная с 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 
});

Это (и более читаемым), чем использование цикла in-in.

Поддерживается в этих браузерах:

  • Firefox (Gecko): 4 (2.0)
  • Хром: 5
  • Internet Explorer: 9

См. ссылка на сайт Mozilla Developer Network Object.keys () для дальнейшего информация.

783
ответ дан SetFreeByTruth 19 August 2018 в 14:29
поделиться
  • 1
    Это теперь более широко поддерживается: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… – Dom Vinyard 29 January 2014 в 16:00
  • 2
    И если вам нужна поддержка старых браузеров, вы можете использовать этот polyfill – KyleMit 5 May 2014 в 16:55
  • 3
    В средах, поддерживающих эту языковую конструкцию, этот метод позволяет вызвать Array.foreach: Object.keys(myObject).forEach(function(key,index) { //key = the name of the object key //index = the ordinal position of the key within the object }); – Todd Price 6 November 2014 в 19:46
  • 4
    Хорошее решение. Но как разбить итерацию ?! – AJ_83 25 January 2017 в 09:19
  • 5
    @ AJ_83 Нет хорошего способа вырваться из forEach (). Используйте some () в этом случае и верните true, чтобы сломать – Daniel Ziegler 23 March 2017 в 11:47

Объекты в JavaScript являются наборами свойств и поэтому могут быть закодированы в a для каждого оператора.

Вы должны думать о obj как о наборе значений ключей.

8
ответ дан user 19 August 2018 в 14:29
поделиться
  • 1
    ! с тем важным различием, что эти «списки свойств» могут иметь имена как ключи, в то время как обычные массивы JS могут иметь только числа в виде ключей. – Qqwy 29 November 2011 в 16:38
  • 2
    это было бы лучшим решением (object.entries ...), но я не могу его использовать. Если вы хотите сделать это несколько раз и не можете поддерживать его в своей структуре, вы можете использовать polyfill на этой странице: developer.mozilla.org/nl/docs/Web/JavaScript/Reference/… – Mario 4 October 2017 в 08:21
  • 3
    Третье предложение велико, если вы только значения свойств. Потрясающие! – gnzg 24 April 2018 в 16:02

Цикл for ... in представляет каждое свойство в объекте, потому что он похож на цикл for. Вы определили propt в цикле for ... in, выполнив:

    for(var propt in obj){
alert(propt + ': ' + obj[propt]);
}

A for ... in loop итерации через перечислимые свойства объекта. Какую бы переменную вы не определяли или не вводили в цикл for ... in, каждый раз, когда она переходит к следующему свойству, она выполняет итерацию. Переменная в цикле for ... in повторяется через клавиши, но значение этого значения является значением ключа. Например:

    for(var propt in obj) {
      console.log(propt);//logs name
      console.log(obj[propt]);//logs "Simon"
    }

Вы можете видеть, как переменная отличается от значения переменной. Напротив, a для ... цикла делает обратное.

Надеюсь, это поможет.

10
ответ дан Vappor Washmade 19 August 2018 в 14:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: