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




удалить свойство объекта js (20)

У меня есть JavaScript-объект, например:

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

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

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


Object.keys (obj): массив

извлекает все строковые ключи всех перечислимых собственных (не наследуемых) свойств.

Таким образом, он дает тот же список ключей, что и вы, путем тестирования каждого ключа объекта с помощью hasOwnProperty. Вам не нужна эта дополнительная тестовая операция, а не Object.keys( obj ).forEach(function( key ){}) должна быть быстрее. Докажем это:

var uniqid = function(){
			var text = "",
					i = 0,
					possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
			for( ; i < 32; i++ ) {
					text += possible.charAt( Math.floor( Math.random() * possible.length ) );
			}
			return text;
		}, 
		CYCLES = 100000,
		obj = {}, 
		p1,
		p2,
		p3,
		key;

// Populate object with random properties
Array.apply( null, Array( CYCLES ) ).forEach(function(){
	obj[ uniqid() ] = new Date()
});

// Approach #1
p1 = performance.now();
Object.keys( obj ).forEach(function( key ){
	var waste = obj[ key ];
});

p2 = performance.now();
console.log( "Object.keys approach took " + (p2 - p1) + " milliseconds.");

// Approach #2
for( key in obj ) {
	if ( obj.hasOwnProperty( key ) ) {
		var waste = obj[ key ];
	}
}

p3 = performance.now();
console.log( "for...in/hasOwnProperty approach took " + (p3 - p2) + " milliseconds.");

В моем Firefox у меня есть следующие результаты

  • Подход Object.keys составил 40.21101451665163 миллисекунд.
  • для ... in / hasOwnProperty принят 98.26163508463651 миллисекунд.

PS. на Chrome разница еще больше http://codepen.io/dsheiko/pen/JdrqXa

PS2: В ES6 (EcmaScript 2015) вы можете повторить итеративный объект:

let map = new Map().set('a', 1).set('b', 2);
for (let pair of map) {
    console.log(pair);
}

// OR 
let map = new Map([
    [false, 'no'],
    [true,  'yes'],
]);
map.forEach((value, key) => {
    console.log(key, value);
});


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

Более подробную информацию вы можете найти на Object.keys()

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

Для старого браузера у вас есть simple и Object.keys() полиспол

UPD:

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

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


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

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

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

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

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

    _.forIn(obj, function(value, key) {
        console.log(key, value);
    });
    

    _.forIn() выполняет _.forIn() над собственными и унаследованными перечислимыми свойствами объекта, тогда как _.forOwn() выполняет _.forOwn() только по собственным свойствам объекта (в основном проверка функции hasOwnProperty ). Для простых объектов и объектных литералов любой из этих методов будет работать нормально.

Как правило, все описанные методы имеют одинаковое поведение с любыми поставленными объектами. Кроме того, использование native for..in цикла for..in обычно будет быстрее любой абстракции, такой как jQuery.each() , эти методы значительно проще в использовании, требуют меньше кодирования и обеспечивают лучшую обработку ошибок.


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

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


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


Вы можете добавить простую функцию 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-Methods, вы можете назвать его своим уникальным именем.


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

Вот фрагмент:

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

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


Интересно, что люди в этих ответах затронули оба Object.keys() и for...of но никогда не комбинировали их:

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

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

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

Без создания реального объекта Map, который не имеет приятного синтаксического сахара.

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

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

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


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

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

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


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

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

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

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


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

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

Циклы могут быть довольно интересными при использовании чистого 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 для массивов, который в основном создал новый улучшенный способ циклического преобразования массивов при сохранении неизменяемых объектов со старым многословным и запутанным циклом , Но странная часть заключается в том, что этот новый метод forEach не поддерживает break который привел ко всем видам других проблем.

В основном в 2011 году не существует реального надежного способа циклирования в JavaScript, кроме того, что многие популярные библиотеки (jQuery, Underscore и т. Д.) Решили повторно реализовать.

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

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


через прототип с 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

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

Object.entries(p);

Объект становится итератором, когда он реализует метод .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

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

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

Шаг 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


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

let arrValues = Object.values( yourObject) ;

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

MDN DOCS Object.values ​​()

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

let arrKeys   = Object.keys(yourObject);

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>


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

for (let o of Object.getOwnPropertyNames(Math)) {
  console.log(o);
}

Я иногда использую это для быстрого тестирования всех функций на объектах с простыми входами и выходами.


Если кто-то нуждается в цикле через 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");
      }
   }
}


Я бы сделал это, а не проверял 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");
}






each