How do I loop through or enumerate a JavaScript ob

2018-12-30 22:29发布

I have a JavaScript object like the following:

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

Now I want to loop through all p elements (p1, p2, p3...) And get their keys and values. How can I do that?

I can modify the JavaScript object if necessary. My ultimate goal is to loop through some key value pairs and if possible I want to avoid using eval.

30条回答
无与为乐者.
2楼-- · 2018-12-30 22:48

Preface:

  • Object properties can be own (the property is on the object itself) or inherited (not on the object itself, on one of its prototypes).
  • Object properties can be enumerable or non-enumerable. Non-enumerable properties are left out of lots of property enumerations/arrays.
  • Property names can be strings or Symbols. Properties whose names are Symbols are left out of lots of property enumerations/arrays.

Here in 2018, your options for looping through an object's properties are:

  1. for-in [MDN, spec] — A loop structure that loops through the names of an object's enumerable properties, including inherited ones, whose names are strings
  2. Object.keys [MDN, spec] — A function providing an array of the names of an object's own, enumerable properties whose names are strings.
  3. Object.values [MDN, spec] — A function providing an array of the values of an object's own, enumerable properties.
  4. Object.entries [MDN, spec] — A function providing an array of the names and values of an object's own, enumerable properties.
  5. Object.getOwnPropertyNames [MDN, spec] — A function providing an array of the names of an object's own properties (even non-enumerable ones) whose names are strings.
  6. Object.getOwnPropertySymbols [MDN, spec] — A function providing an array of the names of an object's own properties (even non-enumerable ones) whose names are Symbols.
  7. Reflect.ownKeys [MDN, spec] — A function providing an array of the names of an object's own properties (even non-enumerable ones), whether those names are strings or Symbols.
  8. If you want all of an object's properties, including non-enumerable inherited ones, you need to use a loop and Object.getPrototypeOf [MDN, spec] and use Object.getOwnPropertyNames, Object.getOwnPropertySymbols, or Reflect.ownKeys on each object in the prototype chain (example at the bottom of this answer).

With all of them except for-in, you'd use some kind of looping construct on the array (for, for-of, forEach, etc.).

Examples:

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 (with a for-of loop, but you can use any looping 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}`);
}

All properties, including inherited non-enumerable ones:

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

查看更多
无与为乐者.
3楼-- · 2018-12-30 22:49

You have to use the for-in loop

But be very careful when using this kind of loop, because this will loop all the properties along the prototype chain.

Therefore, when using for-in loops, always make use of the hasOwnProperty method to determine if the current property in iteration is really a property of the object you're checking on:

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
}
查看更多
低头抚发
4楼-- · 2018-12-30 22:49

If anybody needs to loop through arrayObjects with condition:

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

查看更多
旧人旧事旧时光
5楼-- · 2018-12-30 22:52

since ES06 you can get the values of an object as array with

let arrValues = Object.values( yourObject) ;

it return the an array of the object values and it not extract values from Prototype!!

MDN DOCS Object.values()

and for keys ( allready answerd before me here )

let arrKeys   = Object.keys(yourObject);
查看更多
忆尘夕之涩
6楼-- · 2018-12-30 22:53

Loops can be pretty interesting when using pure JavaScript. It seems that only ECMA6 (New 2015 JavaScript specification) got the loops under control. Unfortunately as I'm writing this, both Browsers and popular Integrated development environment (IDE) are still struggling to support completely the new bells and whistles.

At a glance here is what a JavaScript object loop look like before 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;
  }
}

Also, I know this is out of scope with this question but in 2011, ECMAScript 5.1 added the forEach method for Arrays only which basically created a new improved way to loop through arrays while still leaving non iterable objects with the old verbose and confusing for loop. But the odd part is that this new forEach method does not support break which led to all sorts of other problems.

Basically in 2011, there is not a real solid way to loop in JavaScript other than what many popular libraries (jQuery, Underscore, etc.) decided to re-implement.

As of 2015, we now have a better out of the box way to loop (and break) any object type (including Arrays and Strings). Here is what a loop in JavaScript will eventually look like when the recommendation becomes mainstream:

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

Note that most browsers won't support the code above as of June 18th 2016. Even in Chrome you need to enable this special flag for it to work: chrome://flags/#enable-javascript-harmony

Until this becomes the new standard, the old method can still be used but there are also alternatives in popular libraries or even lightweight alternatives for those who aren't using any of these libraries.

查看更多
姐姐魅力值爆表
7楼-- · 2018-12-30 22:53

An object becomes an iterator when it implements the .next() method

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
查看更多
登录 后发表回答