Javascript foreach วนบนวัตถุอาเรย์แบบเชื่อมโยง


182

ทำไมลูป for-each loop ไม่ทำซ้ำกับอ็อบเจกต์อาเรย์แบบ JavaScript ของฉัน

// defining an array
var array = [];

// assigning values to corresponding keys
array["Main"] = "Main page";
array["Guide"] = "Guide page";
array["Articles"] = "Articles page";
array["Forum"] = "Forum board";

// expected: loop over every item,
// yet it logs only "last" assigned value - "Forum"
for (var i = 0; i < array.length; i++) {
    console.log(array[i]);
}

แก้ไข: jQuery each()อาจมีประโยชน์: https://api.jquery.com/jQuery.each/


1
คุณสร้างอาร์เรย์ แต่ใช้เป็นแผนที่ ดูเหมือนว่าคุณต้องการวัตถุธรรมดาแทน
Jon

4
ไม่มีสิ่งใดassociative arraysใน JS: มันเป็น Array ธรรมดาหรือ Object ไม่มีสิ่งใดขัดขวางการเพิ่มคุณสมบัติที่ไม่ใช่ตัวเลขArrayแต่ไม่ได้ทำให้คุณสมบัติassociativeโดยเฉพาะอย่างยิ่งlengthไม่นับคุณสมบัติเหล่านี้โดยอัตโนมัติ
raina77ow

3
Re: ไม่มีสิ่งต่าง ๆ เช่นอาเรย์เชื่อมโยงใน JS - worded อีกวิธี: JavaScript ใช้ชื่อ "Object" แทนชื่อ "associative array" แต่มันไม่มีคุณสมบัติ ".length"
Jesse Chisholm

คำตอบ:


315

.lengthคุณสมบัติติดตามเฉพาะคุณสมบัติกับดัชนีที่เป็นตัวเลข (คีย์) คุณกำลังใช้สตริงสำหรับคีย์

คุณสามารถทำได้:

var arr_jq_TabContents = {}; // no need for an array

arr_jq_TabContents["Main"] = jq_TabContents_Main;
arr_jq_TabContents["Guide"] = jq_TabContents_Guide;
arr_jq_TabContents["Articles"] = jq_TabContents_Articles;
arr_jq_TabContents["Forum"] = jq_TabContents_Forum;

for (var key in arr_jq_TabContents) {
    console.log(arr_jq_TabContents[key]);
}

เพื่อความปลอดภัยเป็นความคิดที่ดีในการวนรอบเช่นนี้เพื่อให้แน่ใจว่าไม่มีคุณสมบัติใด ๆ ที่เป็นผลลัพธ์ของการสืบทอด:

for (var key in arr_jq_TabContents) {
  if (arr_jq_TabContents.hasOwnProperty(key))
    console.log(arr_jq_TabContents[key]);
}

แก้ไข - ตอนนี้อาจเป็นความคิดที่ดีที่จะทราบว่าObject.keys()ฟังก์ชั่นนี้มีอยู่ในเบราว์เซอร์ที่ทันสมัยและในโหนด ฯลฯ ฟังก์ชั่นนั้นจะส่งคืนคีย์ "ของตัวเอง" ของวัตถุเป็นอาร์เรย์:

Object.keys(arr_jq_TabContents).forEach(function(key, index) {
  console.log(this[key]);
}, arr_jq_TabContents);

ฟังก์ชันการเรียกกลับที่ส่งผ่านไปเรียกว่ามีแต่ละคีย์และดัชนีที่สำคัญในอาร์เรย์ที่ส่งกลับโดย.forEach() Object.keys()มันยังผ่านอาร์เรย์ซึ่งฟังก์ชันทำซ้ำ แต่อาร์เรย์นั้นไม่ได้มีประโยชน์สำหรับเราจริงๆ เราต้องเดิมวัตถุ ที่สามารถเข้าถึงได้โดยตรงโดยชื่อ แต่ (ในความคิดของฉัน) มันเล็ก ๆ น้อย ๆ ที่ดีกว่าที่จะผ่านมันอย่างชัดเจนซึ่งจะทำโดยผ่านการโต้แย้งที่สองเพื่อ.forEach()- วัตถุต้นฉบับ - ซึ่งจะถูกผูกไว้thisในโทรกลับ (เพิ่งเห็นว่าสิ่งนี้ถูกบันทึกไว้ในความคิดเห็นด้านล่าง)


Whats นี้var arr_jq_TabContents = {};? ฉันหมายถึง {}
Szymon Toda

1
@ Ultra มันเป็นวัตถุที่ว่างเปล่าตามตัวอักษร มันหมายถึงว่าตัวแปรนั้นเริ่มต้นได้ด้วยการอ้างอิงไปยังวัตถุที่ว่างเปล่าใหม่
Pointy

@Ultra คุณไม่ต้องการ Array instance เพราะในโค้ดนั้นคุณไม่ได้ใช้มันเหมือนอาร์เรย์ JavaScript JavaScript ไม่มี "อาร์เรย์ที่เชื่อมโยง" เหมือนกับภาษาอื่น ๆ
Pointy

1
ความแตกต่างระหว่างการกำหนด[]และ{}คืออะไร? เฉพาะต้นแบบที่แตกต่างกันอย่างไร
SoonDead

8
แทนที่จะใช้ hasOwnProperty มันควรจะเป็นไปได้ในทุกเว็บเบราว์เซอร์ที่ทันสมัยเพื่อทำซ้ำมากกว่ากุญแจของวัตถุโดยใช้: Object.keys(arr_jq_TabContents).forEach( function(key) { ... } );
Gregory Bell

80

นี่เป็นวิธีการที่ง่ายมาก ข้อดีคือคุณสามารถรับกุญแจได้เช่นกัน:

for (var key in array) {
    var value = array[key];
    console.log(key, value);
}

สำหรับ ES6:

array.forEach(value => {
  console.log(value)
})  

สำหรับ ES6: (หากคุณต้องการค่าดัชนีและอาร์เรย์เอง)

array.forEach((value, index, self) => {
  console.log(value, index, self)
})  

12
อย่าใช้varในลูปเพื่อแนะนำการกำหนดขอบเขตซึ่งไม่มีอยู่ ใช้varด้านหน้าลูปหรือletลูป
ceving

2
@ceving คุณสามารถอธิบายเพิ่มเติมเกี่ยวกับสาเหตุที่ไม่ใช้ var in loops ได้ไหม? ฉันมาจากพื้นหลัง C ++ / PHP และฉันไม่เข้าใจสิ่งนี้ การกำหนดขอบเขตมีอยู่ในลูป แต่เป็นการชั่วคราวดังนั้นฉันไม่แน่ใจว่าคุณหมายถึงอะไร
Dennis

6
@Dennis ในภาษาส่วนใหญ่การประกาศตัวแปรในforลูปจะสร้างขอบเขตที่ จำกัด เฉพาะเนื้อความของforลูป แต่ใน JavaScript ตัวแปรที่ประกาศโดยvarจะทำงานทั่วโลกแม้ว่าคุณจะเขียนมันในforวง ดูที่นี่: davidwalsh.name/for-and-against-let
ceving

1
ไม่ใช่การรั่วไหลของหน่วยความจำต่อ se แต่แน่นอน "memory spills" varใน Javascript สร้างตัวแปรในหน่วยความจำแม้หลังจากวนรอบเสร็จแล้ว
ahnbizcad

ฉันคิดว่าจุดของความคิดเห็นเหล่านี้เกี่ยวกับการใช้ "var" คือตอนนี้ใช้ "ให้" โดยทั่วไป แต่เฉพาะในวง เหตุผลได้อธิบายไว้ข้างต้น แต่โดยสรุปแล้วมันเป็นเพราะขอบเขต "var" สร้างขอบเขตทั่วโลก
DeeZone

6

มีตัวอย่างที่ตรงไปตรงมาอยู่แล้ว แต่ฉันสังเกตว่าคุณได้ถามคำถามของคุณว่าคุณอาจมาจากพื้นหลังของ PHP และคุณคาดหวังว่า JavaScript จะทำงานในลักษณะเดียวกัน - ไม่ได้ PHP arrayแตกต่างจาก JavaScript Arrayอย่างมาก

ใน PHP อาเรย์แบบเชื่อมโยงสามารถทำสิ่งที่อาเรย์ที่ทำดัชนีเป็นตัวเลขได้ส่วนใหญ่ ( array_*ฟังก์ชั่นใช้งานได้คุณสามารถทำได้count()ฯลฯ ) คุณเพียงแค่สร้างอาเรย์และเริ่มกำหนดให้กับดัชนีสตริงแทนตัวเลข

ใน JavaScript ทุกอย่างเป็นวัตถุ (ยกเว้น primitives: string, ตัวเลข, บูลีน) และอาร์เรย์เป็นการใช้งานบางอย่างที่ช่วยให้คุณมีดัชนีตัวเลข สิ่งที่ผลักดันไปยังอาร์เรย์จะมีผลของมันlengthและสามารถซ้ำมากกว่าการใช้วิธีการอาร์เรย์ ( map, forEach, reduce, filter, findฯลฯ ) แต่เนื่องจากทุกอย่างเป็นวัตถุคุณเสมอฟรีเพียงแค่คุณสมบัติกำหนดเพราะนั่นคือสิ่งที่คุณทำเพื่อ วัตถุใด ๆ สัญกรณ์ Square-Bracket เป็นอีกวิธีหนึ่งในการเข้าถึงคุณสมบัติดังนั้นในกรณีของคุณ:

array['Main'] = 'Main Page';

จริงๆแล้วเทียบเท่ากับ:

array.Main = 'Main Page';

จากคำอธิบายของคุณฉันเดาว่าคุณต้องการ 'อาร์เรย์ที่เชื่อมโยง' แต่สำหรับ JavaScript นี่เป็นกรณีง่าย ๆ ในการใช้วัตถุเป็น hashmap นอกจากนี้ฉันรู้ว่ามันเป็นตัวอย่าง แต่หลีกเลี่ยงชื่อที่ไม่มีความหมายซึ่งอธิบายถึงประเภทของตัวแปร (เช่นarray) และชื่อตามสิ่งที่ควรมี (เช่นpages) วัตถุที่เรียบง่ายไม่ได้มีวิธีที่ดีโดยตรงในการวนซ้ำดังนั้นบ่อยครั้งที่เราจะเปลี่ยนเป็นอาร์เรย์ก่อนโดยใช้Objectวิธีการ ( Object.keysในกรณีนี้ - นอกจากนี้ยังมีentriesและvaluesถูกเพิ่มเข้าไปในเบราว์เซอร์บางตัว) ซึ่งเราสามารถวนซ้ำ

// assigning values to corresponding keys
const pages = {
  Main: 'Main page',
  Guide: 'Guide page',
  Articles: 'Articles page',
  Forum: 'Forum board',
};

Object.keys(pages).forEach((page) => console.log(page));


4

นี่เป็นวิธีง่ายๆในการใช้อาเรย์แบบเชื่อมโยงเป็นประเภทวัตถุทั่วไป:

Object.prototype.forEach = function(cb){
   if(this instanceof Array) return this.forEach(cb);
   let self = this;
   Object.getOwnPropertyNames(this).forEach(
      (k)=>{ cb.call(self, self[k], k); }
   );
};

Object({a:1,b:2,c:3}).forEach((value, key)=>{ 
    console.log(`key/value pair: ${key}/${value}`);
});


4

หากสนับสนุน node.js หรือเบราว์เซอร์Object.entries()สามารถใช้เป็นทางเลือกแทนการใช้Object.keys()( https://stackoverflow.com/a/18804596/225291 )

const h = {
  a: 1,
  b: 2
};

Object.entries(h).forEach(([key, value]) => console.log(value));
// logs 1, 2

ในตัวอย่างนี้forEachใช้การกำหนดค่าการทำลายล้างของอาร์เรย์


1

นี่คือ (ส่วนใหญ่) ไม่ถูกต้องในกรณีส่วนใหญ่:

var array = [];
array["Main"] = "Main page";

Mainที่สร้างสถานที่ให้บริการที่ไม่ใช่องค์ประกอบในอาร์เรย์ที่มีชื่อ แม้ว่าอาร์เรย์เป็นวัตถุโดยปกติแล้วคุณไม่ต้องการสร้างคุณสมบัติที่ไม่ใช่องค์ประกอบ

หากคุณต้องการจัดทำดัชนีarrayโดยชื่อเหล่านั้นโดยทั่วไปคุณจะต้องใช้Mapหรือวัตถุธรรมดาไม่ใช่อาร์เรย์

ด้วยMap(ES2015 +) ซึ่งฉันจะโทรหาmapเพราะฉันมีความคิดสร้างสรรค์:

let map = new Map();
map.set("Main", "Main page");

แล้วคุณย้ำโดยใช้ iterators จากมันvalues, keysหรือentriesวิธีการเช่น:

for (const value of map.values()) {
    // Here, `value` will be `"Main page"`, etc.
}

ใช้วัตถุธรรมดาที่ฉันจะเรียกอย่างสร้างสรรค์obj:

let obj = Object.create(null); // Creates an object with no prototype
obj.Main = "Main page"; // Or: `obj["Main"] = "Main page";`

แล้วคุณต้องการย้ำเนื้อหาของใช้Object.keys, Object.valuesหรือObject.entriesตัวอย่างเช่น:

for (const value of Object.values(proches_X)) {
    // Here, `value` will be `"Main page"`, etc.
}

0

var obj = {
  no: ["no", 32],
  nt: ["no", 32],
  nf: ["no", 32, 90]
};

count = -1; // which must be static value
for (i in obj) {
  count++;
  if (obj.hasOwnProperty(i)) {
    console.log(obj[i][count])
  };
};

ในรหัสนี้ฉันใช้วิธีการวงเล็บสำหรับค่าโทรในอาร์เรย์เพราะมันมีอาร์เรย์ แต่สั้น ๆ ความคิดที่ตัวแปรฉันมีคีย์ของทรัพย์สินและกับวงที่เรียกว่าทั้งสองค่าของอาร์เรย์ที่เกี่ยวข้อง

วิธีการที่สมบูรณ์แบบหากคุณสนใจกดเหมือน


คุณไม่ได้วนรอบอาร์เรย์คุณกำลังวนลูปผ่านวัตถุที่มีอาร์เรย์อยู่ในคีย์มัน .. โปรดอ่านคำถามและดูตัวอย่าง
Pedro Joaquín

0

คุณสามารถทำได้

var array = [];

// assigning values to corresponding keys
array[0] = "Main page";
array[1] = "Guide page";
array[2] = "Articles page";
array[3] = "Forum board";


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