รอบคัดเลือกโซน
JavaScript มีเพียงชนิดข้อมูลหนึ่งที่สามารถมีค่าหลายวัตถุ An Arrayเป็นรูปแบบของวัตถุพิเศษ
(ธรรมดา) วัตถุมีรูปแบบ
{key: value, key: value, ...}
อาร์เรย์มีแบบฟอร์ม
[value, value, ...]
ทั้งอาร์เรย์และวัตถุเปิดเผยkey -> value
โครงสร้าง คีย์ในอาร์เรย์ต้องเป็นตัวเลขในขณะที่สตริงใด ๆ สามารถใช้เป็นคีย์ในวัตถุได้ คู่ค่าคีย์จะถูกเรียกว่า"คุณสมบัติ"
คุณสมบัติสามารถเข้าถึงได้โดยใช้เครื่องหมายจุด
const value = obj.someProperty;
หรือเครื่องหมายวงเล็บถ้าชื่อคุณสมบัติจะไม่ใช่ชื่อตัวระบุ JavaScript ที่ถูกต้อง[spec]หรือชื่อคือค่าของตัวแปร:
// the space is not a valid character in identifier names
const value = obj["some Property"];
// property name as variable
const name = "some Property";
const value = obj[name];
ด้วยเหตุผลนั้นองค์ประกอบอาร์เรย์สามารถเข้าถึงได้โดยใช้เครื่องหมายวงเล็บเท่านั้น:
const value = arr[5]; // arr.5 would be a syntax error
// property name / index as variable
const x = 5;
const value = arr[x];
รอ ... แล้ว JSON ล่ะ?
JSON เป็นการแสดงข้อมูลต้นฉบับเดิมเช่น XML, YAML, CSV และอื่น ๆ เพื่อทำงานกับข้อมูลดังกล่าวก่อนอื่นจะต้องมีการแปลงเป็นชนิดข้อมูล JavaScript เช่นอาร์เรย์และวัตถุ (และวิธีการทำงานกับสิ่งเหล่านั้นได้อธิบายไว้) จะอธิบายวิธีแยกวิเคราะห์ JSON ในคำถามแยกวิเคราะห์ JSON ใน JavaScript ได้อย่างไร .
อ่านเพิ่มเติมวัสดุ
วิธีเข้าถึงอาร์เรย์และวัตถุเป็นความรู้พื้นฐานเกี่ยวกับ JavaScript ดังนั้นจึงแนะนำให้อ่านคู่มือMDN JavaScriptโดยเฉพาะส่วนต่างๆ
การเข้าถึงโครงสร้างข้อมูลที่ซ้อนกัน
โครงสร้างข้อมูลที่ซ้อนกันเป็นอาร์เรย์หรือวัตถุที่อ้างถึงอาร์เรย์หรือวัตถุอื่น ๆ เช่นค่าของมันคืออาร์เรย์หรือวัตถุ โครงสร้างดังกล่าวสามารถเข้าถึงได้โดยใช้เครื่องหมายจุดหรือเครื่องหมายอย่างต่อเนื่อง
นี่คือตัวอย่าง:
const data = {
code: 42,
items: [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}]
};
สมมติว่าเราต้องการเข้าถึงname
รายการที่สอง
นี่คือวิธีที่เราสามารถทำได้ทีละขั้นตอน:
อย่างที่เราเห็นdata
เป็นวัตถุดังนั้นเราสามารถเข้าถึงคุณสมบัติโดยใช้เครื่องหมายจุด items
คุณสมบัติการเข้าถึงดังต่อไปนี้:
data.items
ค่าเป็นอาร์เรย์เพื่อเข้าถึงองค์ประกอบที่สองเราต้องใช้เครื่องหมายวงเล็บ:
data.items[1]
ค่านี้เป็นวัตถุและเราใช้เครื่องหมายจุดอีกครั้งเพื่อเข้าถึงname
คุณสมบัติ ดังนั้นเราจึงได้รับ:
const item_name = data.items[1].name;
หรือเราอาจใช้เครื่องหมายวงเล็บสำหรับคุณสมบัติใด ๆ โดยเฉพาะอย่างยิ่งถ้าชื่อมีอักขระที่จะทำให้มันไม่ถูกต้องสำหรับการใช้เครื่องหมายจุด:
const item_name = data['items'][1]['name'];
ฉันกำลังพยายามเข้าถึงอสังหาริมทรัพย์ แต่ฉันได้รับundefined
คืนเท่านั้น
ส่วนใหญ่เมื่อคุณได้รับundefined
วัตถุ / อาร์เรย์ก็ไม่มีคุณสมบัติที่มีชื่อนั้น
const foo = {bar: {baz: 42}};
console.log(foo.baz); // undefined
ใช้console.log
หรือconsole.dir
ตรวจสอบโครงสร้างของวัตถุ / อาร์เรย์ คุณสมบัติที่คุณพยายามเข้าถึงอาจถูกกำหนดบนวัตถุ / อาร์เรย์ที่ซ้อนกัน
console.log(foo.bar.baz); // 42
จะเกิดอะไรขึ้นถ้าชื่อคุณสมบัติเป็นแบบไดนามิกและฉันไม่รู้จักมาก่อน
หากชื่อคุณสมบัติไม่เป็นที่รู้จักหรือเราต้องการเข้าถึงคุณสมบัติทั้งหมดของวัตถุ / องค์ประกอบของอาร์เรย์เราสามารถใช้ลูปfor...in
[MDN]สำหรับวัตถุและลูปfor
[MDN]สำหรับอาร์เรย์เพื่อทำซ้ำคุณสมบัติ / องค์ประกอบทั้งหมด
วัตถุ
ในการวนซ้ำคุณสมบัติทั้งหมดของdata
เราสามารถทำซ้ำวัตถุได้ดังนี้
for (const prop in data) {
// `prop` contains the name of each property, i.e. `'code'` or `'items'`
// consequently, `data[prop]` refers to the value of each property, i.e.
// either `42` or the array
}
ขึ้นอยู่กับว่าวัตถุมาจากไหน (และสิ่งที่คุณต้องการทำ) คุณอาจต้องทดสอบในแต่ละการวนซ้ำว่าคุณสมบัตินั้นเป็นสมบัติของวัตถุจริงหรือเป็นสมบัติที่สืบทอดมา คุณสามารถทำเช่นนี้กับ[MDN]Object#hasOwnProperty
เป็นทางเลือกให้for...in
กับhasOwnProperty
คุณสามารถใช้Object.keys
[MDN]จะได้รับอาร์เรย์ของชื่อคุณสมบัติ :
Object.keys(data).forEach(function(prop) {
// `prop` is the property name
// `data[prop]` is the property value
});
อาร์เรย์
ในการวนซ้ำองค์ประกอบทั้งหมดของdata.items
อาร์เรย์เราใช้การfor
วนซ้ำ:
for(let i = 0, l = data.items.length; i < l; i++) {
// `i` will take on the values `0`, `1`, `2`,..., i.e. in each iteration
// we can access the next element in the array with `data.items[i]`, example:
//
// var obj = data.items[i];
//
// Since each element is an object (in our example),
// we can now access the objects properties with `obj.id` and `obj.name`.
// We could also use `data.items[i].id`.
}
หนึ่งอาจใช้for...in
เพื่อทำซ้ำมากกว่าอาร์เรย์ แต่มีเหตุผลที่ควรหลีกเลี่ยงสิ่งนี้: ทำไม 'สำหรับ (รายการ var ในรายการ)' กับอาร์เรย์ถือว่าการปฏิบัติที่ไม่ดีใน JavaScript? .
ด้วยการรองรับเบราว์เซอร์ที่เพิ่มขึ้นของ ECMAScript 5 วิธีการเรียงลำดับforEach
[MDN]จึงกลายเป็นทางเลือกที่น่าสนใจเช่นกัน:
data.items.forEach(function(value, index, array) {
// The callback is executed for each element in the array.
// `value` is the element itself (equivalent to `array[index]`)
// `index` will be the index of the element in the array
// `array` is a reference to the array itself (i.e. `data.items` in this case)
});
ในสภาพแวดล้อมที่รองรับ ES2015 (ES6) คุณสามารถใช้ลูป[MDN]ซึ่งไม่เพียงทำงานได้กับอาร์เรย์เท่านั้น แต่ยังสามารถใช้ซ้ำได้ :for...of
for (const item of data.items) {
// `item` is the array element, **not** the index
}
ในการวนซ้ำแต่ละครั้งfor...of
จะให้องค์ประกอบถัดไปของการวนซ้ำโดยตรงไม่มีดัชนี "" ในการเข้าถึงหรือใช้
เกิดอะไรขึ้นถ้าฉันไม่รู้จัก "ความลึก" ของโครงสร้างข้อมูล?
นอกเหนือจากคีย์ที่ไม่รู้จัก "ความลึก" ของโครงสร้างข้อมูล (เช่นจำนวนวัตถุที่ซ้อนกัน) ที่มีอาจไม่เป็นที่รู้จักเช่นกัน วิธีเข้าถึงคุณสมบัติที่ซ้อนกันระดับลึกมักขึ้นอยู่กับโครงสร้างข้อมูลที่แน่นอน
แต่ถ้าโครงสร้างข้อมูลมีรูปแบบการทำซ้ำเช่นการเป็นตัวแทนของต้นไม้ไบนารีวิธีการแก้ปัญหามักจะรวมถึงการเข้าถึง[Wikipedia]แบบซ้ำ ๆ ในแต่ละระดับของโครงสร้างข้อมูล
นี่คือตัวอย่างที่จะได้รับโหนดใบแรกของต้นไม้ไบนารี:
function getLeaf(node) {
if (node.leftChild) {
return getLeaf(node.leftChild); // <- recursive call
}
else if (node.rightChild) {
return getLeaf(node.rightChild); // <- recursive call
}
else { // node must be a leaf node
return node;
}
}
const first_leaf = getLeaf(root);
const root = {
leftChild: {
leftChild: {
leftChild: null,
rightChild: null,
data: 42
},
rightChild: {
leftChild: null,
rightChild: null,
data: 5
}
},
rightChild: {
leftChild: {
leftChild: null,
rightChild: null,
data: 6
},
rightChild: {
leftChild: null,
rightChild: null,
data: 7
}
}
};
function getLeaf(node) {
if (node.leftChild) {
return getLeaf(node.leftChild);
} else if (node.rightChild) {
return getLeaf(node.rightChild);
} else { // node must be a leaf node
return node;
}
}
console.log(getLeaf(root).data);
วิธีทั่วไปในการเข้าถึงโครงสร้างข้อมูลแบบซ้อนโดยใช้คีย์และความลึกที่ไม่รู้จักคือการทดสอบชนิดของค่าและดำเนินการตามนั้น
นี่คือตัวอย่างที่เพิ่มค่าดั้งเดิมทั้งหมดภายในโครงสร้างข้อมูลที่ซ้อนอยู่ในอาร์เรย์ (สมมติว่าไม่มีฟังก์ชันใด ๆ ) หากเราพบวัตถุ (หรืออาเรย์) เราก็โทรหาtoArray
ค่านั้นอีกครั้ง (การโทรซ้ำ)
function toArray(obj) {
const result = [];
for (const prop in obj) {
const value = obj[prop];
if (typeof value === 'object') {
result.push(toArray(value)); // <- recursive call
}
else {
result.push(value);
}
}
return result;
}
const data = {
code: 42,
items: [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}]
};
function toArray(obj) {
const result = [];
for (const prop in obj) {
const value = obj[prop];
if (typeof value === 'object') {
result.push(toArray(value));
} else {
result.push(value);
}
}
return result;
}
console.log(toArray(data));
ผู้ช่วย
เนื่องจากโครงสร้างของวัตถุหรืออาร์เรย์ที่ซับซ้อนนั้นไม่จำเป็นต้องชัดเจนเราจึงสามารถตรวจสอบค่าในแต่ละขั้นตอนเพื่อตัดสินใจว่าจะเคลื่อนที่ต่อไปอย่างไร console.log
[MDN]และconsole.dir
[MDN]ช่วยเราทำสิ่งนี้ ตัวอย่างเช่น (ผลลัพธ์ของคอนโซล Chrome):
> console.log(data.items)
[ Object, Object ]
ที่นี่เราจะเห็นว่าdata.items
เป็นอาร์เรย์ที่มีสององค์ประกอบซึ่งเป็นทั้งวัตถุ ในคอนโซล Chrome วัตถุสามารถขยายและตรวจสอบได้ทันที
> console.log(data.items[1])
Object
id: 2
name: "bar"
__proto__: Object
นี้บอกเราว่าdata.items[1]
เป็นวัตถุและหลังจากที่ขยายเราจะเห็นว่ามันมีสามคุณสมบัติid
, และname
__proto__
หลังเป็นคุณสมบัติภายในที่ใช้สำหรับโซ่ต้นแบบของวัตถุ แม้ว่าลูกโซ่ต้นแบบและการสืบทอดอยู่นอกขอบเขตสำหรับคำตอบนี้แล้ว