ทำซ้ำผ่านคุณสมบัติของวัตถุ


2040

var obj = {
    name: "Simon",
    age: "20",
    clothing: {
        style: "simple",
        hipster: false
    }
}

for(var propt in obj){
    console.log(propt + ': ' + obj[propt]);
}

ตัวแปรproptแสดงคุณสมบัติของวัตถุอย่างไร มันไม่ใช่วิธีการหรือคุณสมบัติในตัว ทำไมมันจึงเกิดขึ้นกับทุกคุณสมบัติในวัตถุ?


11
if (typeof(obj[propt]) === 'object') {/ * ทำอีกครั้ง * /}
noob

13
ขอโทษจริงๆสำหรับคำถามนี้ ฉันรู้ว่าลูปคืออะไรฉันไม่สามารถมุ่งหน้าไปที่ "วนลูปผ่านคุณสมบัติของวัตถุ" ซึ่งตอนนี้ฉันคิดว่ามันจะเคลียร์แล้ว นอกจากนี้พวกเขายังแนะนำฉันด้วย "JavaScript ทีละขั้นตอนรุ่นที่ 2 - Steve Suehring ที่โรงเรียน
Rafay

242
นี่คือคำถามที่เริ่มต้นที่ดี ฉันจะเพิ่มว่าฉันมีประสบการณ์วิชาชีพ 15 ปีกับภาษาอื่นและฉันต้องการคำตอบนี้ ฉันจะบวก 2000 ถ้าทำได้
Nathan C. Tresch

60
บ้าจัง แต่ฉันได้มาที่หน้านี้ทุกสองสามเดือนเป็นเวลาหลายปีเพื่อเรียนรู้ไวยากรณ์ใหม่เกี่ยวกับวิธีการทำสิ่งนี้ ฉันไม่สนใจที่จะจำวิธีการทำเช่นนี้ ... ฉันแค่จำได้ว่าหน้านี้อยู่ที่นี่เสมอดังนั้น
HDave

14
นี่คือหน้าแปลกที่สุดที่ฉันเคยเห็นใน StackOverflow หากคุณอ่านคำถามอย่างระมัดระวังคำตอบเพียงคำเดียวจะเริ่มตอบคำถามที่ถูกถามจริงและมีคะแนน -6 คำตอบให้คะแนนสูงสุดซึ่งเป็นที่ยอมรับไม่เพียง แต่ตอบไม่ได้ แต่เป็นเรื่องที่ผิด

คำตอบ:


2426

การวนซ้ำคุณสมบัติต้องใช้การhasOwnPropertyตรวจสอบเพิ่มเติมนี้:

for (var prop in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, prop)) {
        // do stuff
    }
}

มันจำเป็นเพราะต้นแบบของวัตถุมีคุณสมบัติเพิ่มเติมสำหรับวัตถุที่เป็นส่วนหนึ่งของวัตถุทางเทคนิค คุณสมบัติเพิ่มเติมเหล่านี้ได้รับการสืบทอดมาจากคลาสของวัตถุฐาน objแต่ยังคงคุณสมบัติของ

hasOwnProperty ตรวจสอบเพื่อดูว่านี่เป็นคุณสมบัติเฉพาะของคลาสนี้หรือไม่และไม่ได้รับมรดกจากคลาสพื้นฐาน


นอกจากนี้ยังเป็นไปได้ที่จะเรียกhasOwnPropertyผ่านวัตถุเอง:

if (obj.hasOwnProperty(prop)) {
    // do stuff
}

แต่สิ่งนี้จะล้มเหลวหากวัตถุนั้นมีเขตข้อมูลที่ไม่เกี่ยวข้องซึ่งมีชื่อเดียวกัน:

var obj = { foo: 42, hasOwnProperty: 'lol' };
obj.hasOwnProperty('foo');  // TypeError: hasOwnProperty is not a function

นั่นเป็นเหตุผลที่ปลอดภัยกว่าที่จะโทรหาObject.prototypeแทน:

var obj = { foo: 42, hasOwnProperty: 'lol' };
Object.prototype.hasOwnProperty.call(obj, 'foo');  // true

21
@BT ตามเอกสารประกอบของ Mozilla : "หากคุณต้องการพิจารณาคุณสมบัติที่แนบกับวัตถุเท่านั้นไม่ใช่ต้นแบบให้ใช้ getOwnPropertyNames หรือทำการตรวจสอบ hasOwnProperty (คุณสมบัติสามารถใช้ได้เช่นกัน)
davidmdem

3
ประเด็นของการโทรobject.hasOwnProperty()คืออะไร? ความจริงที่propertyมีค่าอะไรไม่ได้หมายความว่ามันมีอยู่objectหรือไม่?
Alex S

6
เนื่องจาก Alex S ต้นแบบของวัตถุมีคุณสมบัติเพิ่มเติมสำหรับวัตถุที่เป็นส่วนหนึ่งของวัตถุทางเทคนิค พวกเขาจะได้รับมรดกมาจากคลาสวัตถุฐาน แต่พวกเขายังคงคุณสมบัติ hasOwnProperty เพียงตรวจสอบเพื่อดูว่านี่เป็นคุณสมบัติที่เฉพาะเจาะจงกับชั้นนี้และไม่ได้รับหนึ่งมาจากชั้นฐาน คำอธิบายที่ดี: brianflove.com/2013/09/05/javascripts-hasownproperty-method
Kyle Richter

87
ฉันรู้สึกว่าฉันควรพูดถึงอย่างไรก็ตาม Object.keys (obj) ตอนนี้เป็นทางออกที่ดีกว่ามากสำหรับการรับกุญแจของวัตถุเอง ลิงก์ไปยังเอกสารประกอบ Mozilla: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ …
Kyle Richter

9
ข้อมูลสำคัญชิ้นหนึ่งหายไป เป็นสตริงที่นี่ควรจะได้รับการเรียกว่าproperty propertyNameมิฉะนั้นอาจทำให้เกิดความสับสนสำหรับมือใหม่ JS ifเหมือนตัวเองคือสิ่งที่ต้องทำภายใน
Neolisk

1136

ในฐานะของ JavaScript 1.8.5 คุณสามารถใช้Object.keys(obj)เพื่อรับ Array of Properties ที่กำหนดไว้บนวัตถุนั้น (อันที่คืนค่าจริง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 (ตุ๊กแก): 4 (2.0)
  • Chrome: 5
  • Internet Explorer: 9

ดูมอซิลลานักพัฒนาเครือข่ายObject.keys () 's อ้างอิงสำหรับข้อมูลละเอียดเพิ่มเติม


7
ตอนนี้ได้รับการสนับสนุนอย่างกว้างขวางยิ่งขึ้น: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
......

3
และถ้าคุณต้องการการสนับสนุนสำหรับเบราว์เซอร์เก่าคุณสามารถใช้polyfill
KyleMit

27
ในสภาพแวดล้อมที่รองรับการสร้างภาษานี้วิธีการนี้อนุญาตให้ 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

4
@ AJ_83 ไม่มีวิธีที่ดีที่จะแยกออกจาก forEach () ใช้บางอย่าง () ในกรณีนี้และกลับสู่ความจริงเพื่อทำลาย
Daniel Z.

11
ทำไมถึงอ่านได้มากกว่า for-in? for candidate in candidateStatus... ดูเหมือนว่าฉันจะอ่าน
Jona

309

เด็กผู้หญิงและผู้ชายเราอยู่ในปี 2019 และเราไม่มีเวลามากพอที่จะพิมพ์ ... ดังนั้นขอให้ทำสิ่งนี้ใหม่ ECMAScript 2016 ที่ยอดเยี่ยม:

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

17
สิ่งนี้แตกต่างจากคำตอบของ Danny R อย่างไร
krillgar

27
มันเป็น oneliner และใช้แผนที่แทน forEach และบางคนอาจสนใจคำแนะนำ console.log
Frank Roth

Satly ที่ไม่ทำงานเมื่อobj=window.performance.memory: - / ในกรณีที่เป็นfor inไม่ ievar obj = window.performance.memory; for( key in obj ) console.log( 'key=' + key + ' val=' + obj[key] );
Michaelangel007

2
window.performance.memoryสนับสนุนโดย chrome เท่านั้นและObject.keys(obj)ส่งคืนอาร์เรย์ว่าง .mapนี้มีอะไรจะทำอย่างไรกับ
Frank Roth

ในกรณีที่ใครไม่ต้องการลิงรอบโครงสร้างใหม่ซับเดี่ยวนี้เพื่อทำมากกว่าหนึ่งครั้งพร้อมeฉันโพสต์ส่วนสำคัญนี้ มันเหมือนกับการใช้งานแฮชส่วนใหญ่และใช้( (key) => (value) )แทน{ key => value }แต่ถ้าคุณไม่เคยจัดการกับมันมาก่อนมันจะช่วยให้คุณเห็นภาพได้ดีขึ้น: gist.github.com/the-nose-knows/9f06e745a56ff20519707433e28a4fa8
kayleeFrye_oneck

216

มันเป็นfor...in statement( ข้อมูลจำเพาะMDN , ECMAScript )

คุณสามารถอ่านได้ว่า " สำหรับสถานที่ให้บริการทุกคนในobjวัตถุกำหนดสถานที่ให้บริการในแต่ละที่จะproptตัวแปรในทางกลับกัน"


1
ขอบคุณมากฉันเข้าใจแล้ว ฉันตีหัวอ่านหนังสือและ Google
Rafay

21
เห็นด้วยกับ @RightSaidFred inผู้ดำเนินการและforคำสั่งไม่เกี่ยวข้องเลยfor-inคำแถลงนี้แสดงถึงการผลิตไวยกรณ์ของตัวเอง: for ( LeftHandSideExpression in Expression ),for ( var VariableDeclarationNoIn in Expression )
CMS

2
แปลกคำตอบนี้มีคะแนนโหวตมากโดยเฉพาะอย่างยิ่งเนื่องจากความคิดเห็นยอดนิยมเหล่านี้ดูเหมือนจะขัดแย้ง
Doug Molineux

9
เหตุใดเครื่องหมายนี้จึงเป็นคำตอบ มันอาจจะเป็นหนึ่งที่เป็นประโยชน์น้อยในหัวข้อนี้ ..
computrius

3
คำตอบที่เป็นประโยชน์น้อยที่สุด? ขึ้นอยู่กับสิ่งที่คุณคิดว่า OP กำลังขอ เมื่อฉันอ่านคำถามเป็นครั้งแรกดูเหมือนว่างงงวยเกี่ยวกับกลไกที่ตัวแปรสามารถใช้ในการตรวจสอบคุณสมบัติของวัตถุและคำตอบนี้อธิบายอย่างละเอียด (คำเรียกผิดที่ 'for-in' โดยไม่คำนึงถึง) คำถาม "ทำไมมันถึงเกิดขึ้นกับทุก ๆ ทรัพย์สิน" ฉันเห็นได้ว่า OP กำลังมองหา hasOwnProperty แต่ไม่ทราบ แต่ฉันคิดว่ามันเป็นไปได้มากกว่านี่เป็นสิ่งที่ OP ต้องการรู้และยอมรับผิด ตอบคำถามอื่น :-)
Bumpy

157

ในการนำไปใช้งานล่าสุดของ 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 => ...)

นี่จะเป็นทางออกที่ดีที่สุด (object.entries ... ) แต่ฉันไม่สามารถใช้งานได้ เมื่อคุณต้องการทำเช่นนี้หลายครั้งและไม่สามารถรองรับได้ในกรอบงานของคุณคุณสามารถใช้ polyfill ในหน้านี้: developer.mozilla.org/nl/docs/Web/JavaScript/Reference/
Mario

ข้อเสนอแนะที่สามนั้นยอดเยี่ยมถ้าคุณเพียงแค่ค่าของคุณสมบัติ ! น่ากลัว
Ginzburg


27

หากสภาพแวดล้อมของคุณรองรับES2017ฉันจะแนะนำObject.entries :

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

ดังแสดงในเอกสารประกอบของMozillas Object.entries () :

กระบวนการObject.entries ()วิธีการส่งกลับอาร์เรย์ของคุณสมบัตินับจำนวนคู่ของตัวเองของวัตถุที่สำคัญ [คีย์ค่า] ในลำดับเดียวกันกับที่ให้โดยสำหรับ ... ในวง คุณสมบัติในห่วงโซ่ต้นแบบเช่นกัน)

โดยทั่วไปกับ Object.entries เราสามารถข้ามขั้นตอนพิเศษต่อไปนี้ซึ่งจำเป็นกับเก่ากว่าสำหรับ ... ในลูป:

// This step is not necessary with Object.entries
if (object.hasOwnProperty(property)) {
  // do stuff
}

22

jquery อนุญาตให้คุณทำตอนนี้ได้:

$.each( obj, function( key, value ) {
  alert( key + ": " + value );
});

1
$.each({foo:1, length:0, bar:2}, function(k,v){console.log(k,v)})$ .each ไม่เหมาะสำหรับวัตถุ หากวัตถุมีคุณสมบัติความยาวและค่าของวัตถุนั้นเป็นศูนย์วัตถุทั้งหมดจะถูกปฏิบัติเสมือนเป็นอาร์เรย์ว่างเปล่า
Bob Stein

รายละเอียดเหตุผลที่ผมคิดว่านี่เป็นวิธีการข้อผิดพลาดในการเชิญ
Bob Stein

21

คำตอบของ Dominikนั้นสมบูรณ์แบบฉันแค่ชอบทำอย่างนั้นเพราะมันอ่านง่ายกว่า:

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

    // Do stuff...
}

ควรอยู่Objectกับตัวพิมพ์ใหญ่ o หรือไม่?
Jonathan

18

คำตอบข้างต้นค่อนข้างน่ารำคาญเพราะพวกเขาไม่ได้อธิบายสิ่งที่คุณทำในการวนรอบหลังจากคุณแน่ใจว่ามันเป็นวัตถุ: คุณไม่สามารถเข้าถึงได้โดยตรง! คุณจะส่งมอบคีย์ที่คุณต้องใช้กับ 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;)


15

เพื่อเพิ่มการใช้งานของ 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 สำหรับสตริง, อาร์เรย์, อาร์เรย์ที่พิมพ์, แผนที่และชุด

JS จะพยายามย้ำผ่านคุณสมบัติ iterator Symbol.iteratorเริ่มต้นซึ่งจะต้องกำหนดให้เป็น

หากคุณต้องการที่จะย้ำเหนือวัตถุทั้งหมดคุณสามารถเพิ่มมันเป็นต้นแบบของวัตถุ:

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

สิ่งนี้จะช่วยให้คุณสามารถวนซ้ำค่าของวัตถุที่มีห่วง ...

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

ข้อควรระวัง : ตั้งแต่วันที่เขียนคำตอบนี้ (มิถุนายน 2018) เบราว์เซอร์อื่น ๆ ทั้งหมด แต่ IE สนับสนุนเครื่องกำเนิดและfor...ofการทำซ้ำผ่านSymbol.iterator


แม้ว่าคุณจะไม่ได้ตอบคำถามของ OP จริง ๆ แต่สิ่งนี้มีประโยชน์มากสำหรับฉัน แต่ฉันยังไม่รู้เกี่ยวกับ Reflect
Michiel

15
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
// If there is no keys in obj, it will return empty array = []
// Then it will get it's length, if it has at least one element,
// 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]);
    });
}

3
สวัสดีคุณสามารถเพิ่มข้อมูลเพิ่มเติมเกี่ยวกับคำตอบของคุณได้หรือไม่การให้รหัสเท่านั้นไม่ช่วย
Nicolas

สวัสดี @ Nicolas ฉันได้เพิ่มบรรทัดคำอธิบายบรรทัดในรหัส ให้ฉันรู้ว่าถ้ามันยังไม่ชัดเจน
Fouad Boukredine

เนื่องจากforEach ข้ามค่าว่างฉันคิดว่าคุณสามารถกำจัด if และเพียงแค่ทำObject.keys(obj).forEach(e => console.log(`key=${e} value=${obj[e]}`));ตามคำตอบของ Frank Roth
Darkproduct

12

กระบวนการ for ... in loop แสดงถึงคุณสมบัติแต่ละอย่างในวัตถุเพราะมันเหมือนกับ for for loop คุณกำหนด propt ในวง for ... in โดยทำดังนี้

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

A สำหรับ ... in loop วนซ้ำผ่านคุณสมบัติที่นับได้ของวัตถุ ไม่ว่าคุณจะกำหนดตัวแปรใดหรือวางในลูป for ... in จะเปลี่ยนทุกครั้งที่มันไปยังคุณสมบัติถัดไปที่มันวนซ้ำ ตัวแปรใน for ... in วนซ้ำผ่านคีย์ แต่ค่าของมันคือค่าของคีย์ ตัวอย่างเช่น:

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

คุณสามารถดูว่าตัวแปรแตกต่างจากค่าของตัวแปรอย่างไร ในทางตรงกันข้าม a สำหรับ ... ของลูปจะตรงกันข้าม

ฉันหวังว่านี่จะช่วยได้.


11
let obj = {"a": 3, "b": 2, "6": "a"}

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

// a
// 3
// 2

1
ดังที่ได้กล่าวไว้ในความคิดเห็นอื่น ๆ มีความforEachเหมาะสมมากกว่าที่นี่เนื่องจากmapมีวัตถุประสงค์เพื่อส่งคืนอาร์เรย์ใหม่พร้อมผลลัพธ์ของการเรียกบล็อกโค้ดในแต่ละการวนซ้ำ แต่เราสนใจเฉพาะผลข้างเคียงของการวนซ้ำแต่ละครั้งไม่ใช่ค่าส่งคืนดังนั้นเราจึงไม่ต้องการอาร์เรย์ใหม่ที่mapให้เรา
Danny


10

คุณสามารถใช้ Lodash เอกสารประกอบ

var obj = {a: 1, b: 2, c: 3};
_.keys(obj).forEach(function (key) {
    ...
});

10
ทำไม "คำตอบ" นี้บนโลกถึงมี 10 upvotes ไม่สามารถตอบคำถามได้อย่างสมบูรณ์ ฉันเริ่มสูญเสียศรัทธาในความฉลาดของผู้พัฒนา JS โดยเฉลี่ย
developerbmw

1
@developerbmw ฉันเข้าใจว่าการใช้คุณสมบัติ ES6 นั้นถูกต้องกว่า แต่ฉันได้ตอบเมื่อปีที่แล้ว โปรดแบ่งปันความคิดของคุณกับเราเมื่อคุณมีเวลา
viktarpunko

1
แนวคิดคือให้ความสำคัญกับวิธีการเนทิฟมากกว่าการแนะนำผู้ใช้ให้เพิ่มไลบรารี่ 10,000 บรรทัดลงในหน้าของพวกเขา อย่าเข้าใจฉันผิดฉันชอบใช้ Lodash แต่มีเวลาและสถานที่สำหรับมันและไม่ใช่สิ่งนี้

9

คุณforห่วงคือ iterating objเหนือทุกคุณสมบัติของวัตถุ proptถูกกำหนดในบรรทัดแรกของลูป for มันเป็นสตริงที่เป็นชื่อของทรัพย์สินของobjวัตถุ ในการวนซ้ำครั้งแรกของลูปproptจะเป็น "ชื่อ"


9

วัตถุใน JavaScript คือชุดของคุณสมบัติและสามารถวนซ้ำในสำหรับแต่ละคำสั่ง

คุณควรคิดว่าobjเป็นชุดของค่าคีย์


! ด้วยความแตกต่างที่สำคัญที่ 'รายการคุณสมบัติ' เหล่านี้สามารถมีชื่อเป็นคีย์ได้ในขณะที่อาร์เรย์ JS ปกติสามารถมีตัวเลขเป็นคีย์ได้เท่านั้น
Qqwy

9

ทุกวันนี้คุณสามารถแปลงออบเจกต์ 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);


1
วิธีทำที่น่าสนใจ ขอบคุณสำหรับการfunction*ค้นพบ!
Benj


5

ในขณะที่คำตอบที่ติดอันดับยอดนิยมถูกต้องนี่คือกรณีการใช้งานทางเลือกเช่นหากคุณวนซ้ำวัตถุและต้องการสร้างอาร์เรย์ในที่สุด ใช้.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]
})

4

ยังเพิ่มวิธีแบบเรียกซ้ำ:

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

1
@faiz - ดูความคิดเห็นของฉันมันป้องกันไม่ให้ติดอยู่ในวงวนไม่สิ้นสุดเมื่อคุณเดินวัตถุรางที่มีการอ้างอิงแบบวนรอบ
Ondrej Svejdar

3

สิ่งที่ .. ในลูปคือมันสร้างตัวแปรใหม่ (var someVariable) แล้วเก็บคุณสมบัติของวัตถุที่กำหนดในตัวแปรใหม่นี้ (someVariable) ทีละตัว ดังนั้นหากคุณใช้บล็อก {} คุณสามารถทำซ้ำได้ ลองพิจารณาตัวอย่างต่อไปนี้

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

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

console.log(someVariable); // outputs planet

การลงคะแนนในครั้งนี้เนื่องจากความเรียบง่าย ในกรณีการใช้งานของฉันฉันต้องตรวจสอบคุณสมบัติทั้งหมดในวัตถุเพื่อหาค่าหลบซึ่งเป็นโมฆะไม่ได้กำหนด (เป็นจุดบนกราฟและค่าเหล่านี้ทำให้กราฟไม่สามารถวาดได้) obj[someVariable]จะได้รับค่าแทนชื่อที่ในวงที่คุณเพิ่งจะทำ บางทีเหตุผลที่ถูกลดระดับลงอย่างมากก็เพราะว่ามันไม่ได้เรียกซ้ำ ดังนั้นนี่จะไม่ใช่ทางออกที่เพียงพอหากคุณมีวัตถุที่มีโครงสร้างสูง
แคทธารีนออสบอร์น

@KatharineOsborne หรืออาจเป็นเพราะวลีต่อไปนี้เป็นความลับเล็กน้อย: "ดังนั้นหากคุณใช้บล็อก {} คุณสามารถทำซ้ำได้" รหัสพูดได้มากกว่าตัวอักษร
bvdb

3

ที่นี่ฉันทำซ้ำแต่ละโหนดและสร้างชื่อโหนดที่มีความหมาย ถ้าคุณสังเกตเห็น, 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 แต่วิธีนี้มีประสิทธิภาพที่ดีขึ้นและไม่ชัดเจนน้อยลง


3

โดยทั่วไปคุณต้องการวนลูปผ่านแต่ละคุณสมบัติในวัตถุ

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

obj(prop)<- TypeError: obj ไม่ใช่ฟังก์ชัน
le_m

@le_m ฉันไม่ดี ฉันต้องนำhasOwnPropertyคุณลักษณะออกไปโดยไม่ตั้งใจ มันควรจะใช้งานได้แล้ว
HovyTech

2

ฉันต้องการเพิ่มคำตอบข้างต้นเพราะคุณอาจมีความตั้งใจแตกต่างจาก 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ฯลฯ เมื่อ iterating ผ่านคุณสมบัติของ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]);

            }

     }
}

1

ในการปรับแต่งคำตอบที่ได้รับการยอมรับเพิ่มเติมนั้นมีค่าควรสังเกตว่าถ้าคุณสร้างอินสแตนซ์ของวัตถุด้วย a var object = Object.create(null)แล้วobject.hasOwnProperty(property)จะทำให้เกิด TypeError ดังนั้นในด้านความปลอดภัยคุณต้องเรียกมันจากต้นแบบเช่นนี้

for (var property in object) {
    if (Object.prototype.hasOwnProperty.call(object, property)) {
        // do stuff
    }
}

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.