จะใช้ Maps เมื่อใดแทนที่จะใช้ JavaScript Object ธรรมดา
วัตถุ JavaScript ธรรมดา {คีย์: 'value'} เก็บข้อมูลที่มีโครงสร้าง แต่วัตถุ JS ธรรมดามีข้อ จำกัด :
สตริงและสัญลักษณ์เท่านั้นที่สามารถใช้เป็นกุญแจของวัตถุ หากเราใช้สิ่งอื่น ๆ พูดตัวเลขเป็นกุญแจของวัตถุจากนั้นในระหว่างการเข้าถึงกุญแจเหล่านั้นเราจะเห็นว่ากุญแจเหล่านั้นจะถูกแปลงเป็นสตริงโดยปริยายทำให้เราสูญเสียความมั่นคงของประเภท ชื่อ const = {1: 'one', 2: 'two'}; Object.keys (ชื่อ); // ['1', '2']
มีโอกาสที่จะเขียนทับคุณสมบัติที่สืบทอดมาจากต้นแบบโดยไม่ตั้งใจโดยการเขียนตัวระบุ JS เป็นชื่อที่สำคัญของวัตถุ (เช่น toString, ตัวสร้าง ฯลฯ )
ไม่สามารถใช้วัตถุอื่นเป็นคีย์ของวัตถุดังนั้นจึงไม่สามารถเขียนข้อมูลเพิ่มเติมสำหรับวัตถุโดยการเขียนวัตถุนั้นเป็นคีย์ของวัตถุอื่นและค่าของวัตถุอื่นนั้นจะมีข้อมูลเพิ่มเติม
วัตถุไม่ใช่ตัววนซ้ำ
ขนาดของวัตถุไม่สามารถกำหนดได้โดยตรง
ข้อ จำกัด ของวัตถุเหล่านี้แก้ไขได้โดย Maps แต่เราต้องพิจารณาว่า Maps เป็นส่วนเสริมสำหรับ Objects แทนการแทนที่ โดยทั่วไปแผนที่เป็นเพียงอาร์เรย์ของอาร์เรย์ แต่เราต้องผ่านอาร์เรย์นั้นไปยังวัตถุแผนที่เป็นอาร์กิวเมนต์ด้วยคำหลักใหม่มิฉะนั้นเฉพาะอาร์เรย์ของอาร์เรย์คุณสมบัติที่มีประโยชน์และวิธีการของแผนที่จะไม่สามารถใช้ได้ และจำคู่คีย์ - ค่าภายในอาร์เรย์ของอาร์เรย์หรือแผนที่จะต้องคั่นด้วยเครื่องหมายจุลภาคเท่านั้นไม่มีโคลอนในวัตถุธรรมดา
3 เคล็ดลับในการตัดสินใจว่าจะใช้แผนที่หรือวัตถุ:
ใช้แผนที่เหนือวัตถุเมื่อไม่ทราบรหัสจนกว่าจะถึงเวลาใช้งานเนื่องจากกุญแจที่เกิดขึ้นจากการป้อนข้อมูลของผู้ใช้หรือไม่รู้รหัสสามารถทำลายรหัสซึ่งใช้วัตถุหากคีย์เหล่านั้นเขียนทับคุณสมบัติที่สืบทอดของวัตถุดังนั้นแผนที่จึงปลอดภัยกว่าในกรณีเหล่านั้น ใช้แผนที่เมื่อปุ่มทั้งหมดเป็นประเภทเดียวกันและแผนที่ทั้งหมดเป็นประเภทเดียวกัน
ใช้แผนที่หากไม่จำเป็นต้องเก็บค่าดั้งเดิมไว้เป็นกุญแจ
ใช้วัตถุหากเราจำเป็นต้องดำเนินการกับองค์ประกอบแต่ละอย่าง
ประโยชน์ของการใช้ Maps คือ:
1. แผนที่ยอมรับประเภทของคีย์และรักษาประเภทของคีย์:
เรารู้ว่าหากคีย์ของวัตถุนั้นไม่ใช่สตริงหรือสัญลักษณ์ JS จะแปลงมันเป็นสตริงโดยปริยาย ในทางกลับกัน Map ยอมรับคีย์ชนิดใดก็ได้: สตริง, ตัวเลข, บูลีน, สัญลักษณ์อื่น ๆ และ Map จะรักษาชนิดของคีย์ดั้งเดิม ที่นี่เราจะใช้หมายเลขเป็นกุญแจในแผนที่และมันจะยังคงเป็นตัวเลข:
const numbersMap= new Map();
numbersMap.set(1, 'one');
numbersMap.set(2, 'two');
const keysOfMap= [...numbersMap.keys()];
console.log(keysOfMap); // [1, 2]
ภายในแผนที่เราสามารถใช้วัตถุทั้งหมดเป็นกุญแจได้ อาจมีบางครั้งที่เราต้องการจัดเก็บข้อมูลที่เกี่ยวข้องกับวัตถุโดยไม่ต้องแนบข้อมูลนี้ไว้ในวัตถุเพื่อให้เราสามารถทำงานกับวัตถุแบบลีนได้ แต่ต้องการเก็บข้อมูลบางอย่างเกี่ยวกับวัตถุ ในกรณีเหล่านั้นเราจำเป็นต้องใช้แผนที่เพื่อให้เราสามารถทำให้วัตถุเป็นข้อมูลสำคัญและข้อมูลที่เกี่ยวข้องของวัตถุเป็นค่า
const foo= {name: foo};
const bar= {name: bar};
const kindOfMap= [[foo, 'Foo related data'], [bar, 'Bar related data']];
แต่ข้อเสียของวิธีการนี้คือความซับซ้อนในการเข้าถึงค่าตามคีย์เนื่องจากเราต้องวนซ้ำอาร์เรย์ทั้งหมดเพื่อรับค่าที่ต้องการ
function getBy Key(kindOfMap, key) {
for (const [k, v] of kindOfMap) {
if(key === k) {
return v;
}
}
return undefined;
}
getByKey(kindOfMap, foo); // 'Foo related data'
เราสามารถแก้ปัญหานี้ไม่ให้เข้าถึงคุณค่าโดยตรงโดยใช้แผนที่ที่เหมาะสม
const foo= {name: 'foo'};
const bar= {name: 'bar'};
const myMap= new Map();
myMap.set(foo, 'Foo related data');
myMap.set(bar, 'Bar related data');
console.log(myMap.get(foo)); // 'Foo related data'
เราสามารถทำได้โดยใช้ WeakMap เพียงแค่ต้องเขียน const myMap = new WeakMap () ความแตกต่างระหว่าง Map และ WeakMap คือ WeakMap อนุญาตให้มีการรวบรวมขยะของคีย์ (นี่คือวัตถุ) เพื่อป้องกันการรั่วไหลของหน่วยความจำ WeakMap ยอมรับเฉพาะวัตถุเป็นกุญแจและ WeakMap ได้ลดชุดวิธีการ
2. แผนที่ไม่มีข้อ จำกัด เรื่องชื่อคีย์:
สำหรับวัตถุ JS ธรรมดาเราสามารถเขียนทับคุณสมบัติที่สืบทอดจากต้นแบบได้โดยไม่ตั้งใจและอาจเป็นอันตรายได้ ที่นี่เราจะเขียนทับคุณสมบัติ toString () ของวัตถุนักแสดง:
const actor= {
name: 'Harrison Ford',
toString: 'Actor: Harrison Ford'
};
ทีนี้เราจะนิยาม fn isPlainObject () เพื่อดูว่าอาร์กิวเมนต์ที่ให้มาเป็นวัตถุธรรมดาหรือไม่และ fn นี้ใช้ toString () วิธีการตรวจสอบ:
function isPlainObject(value) {
return value.toString() === '[object Object]';
}
isPlainObject(actor); // TypeError : value.toString is not a function
// this is because inside actor object toString property is a string instead of inherited method from prototype
แผนที่ไม่มีข้อ จำกัด ใด ๆ เกี่ยวกับชื่อคีย์เราสามารถใช้ชื่อคีย์เช่น toString, constructor เป็นต้นที่นี่แม้ว่าวัตถุ actorMap มีคุณสมบัติชื่อ toString แต่วิธี toString () ที่สืบทอดมาจากต้นแบบของวัตถุ objectMap นั้นทำงานได้อย่างสมบูรณ์แบบ
const actorMap= new Map();
actorMap.set('name', 'Harrison Ford');
actorMap.set('toString', 'Actor: Harrison Ford');
function isMap(value) {
return value.toString() === '[object Map]';
}
console.log(isMap(actorMap)); // true
หากเรามีสถานการณ์ที่ผู้ใช้ป้อนข้อมูลสร้างคีย์เราจะต้องใช้กุญแจเหล่านั้นในแผนที่แทนวัตถุธรรมดา นี่เป็นเพราะผู้ใช้สามารถเลือกชื่อฟิลด์ที่กำหนดเองเช่น toString คอนสตรัคเตอร์เป็นต้นจากนั้นชื่อคีย์ดังกล่าวในวัตถุธรรมดาอาจทำลายรหัสที่ใช้วัตถุนี้ในภายหลัง ดังนั้นทางออกที่ถูกต้องคือการผูกสถานะส่วนต่อประสานผู้ใช้กับแผนที่จึงไม่มีวิธีที่จะทำให้แผนที่แตก:
const userCustomFieldsMap= new Map([['color', 'blue'], ['size', 'medium'], ['toString', 'A blue box']]);
3. แผนที่สามารถทำซ้ำได้:
ในการย้ำคุณสมบัติของวัตถุธรรมดาเราต้องการ Object.entries () หรือ Object.keys () Object.entries (plainObject) ส่งคืนอาร์เรย์ของคู่ของค่าคีย์ที่ดึงออกมาจากวัตถุจากนั้นเราสามารถทำลายคีย์และค่าเหล่านั้นและสามารถรับคีย์และค่าปกติ
const colorHex= {
'white': '#FFFFFF',
'black': '#000000'
}
for(const [color, hex] of Object.entries(colorHex)) {
console.log(color, hex);
}
//
'white' '#FFFFFF'
'black' '#000000'
เนื่องจากแผนที่มีการทำซ้ำจึงเป็นเหตุผลว่าทำไมเราไม่ต้องการวิธีการ () วิธีการวนซ้ำในแผนที่และการทำลายคีย์ค่าอาร์เรย์สามารถทำได้โดยตรงบนแผนที่เหมือนกับภายในแผนที่แต่ละองค์ประกอบมีชีวิตเหมือนอาร์เรย์ของคู่ค่าคีย์คั่นด้วยเครื่องหมายจุลภาค .
const colorHexMap= new Map();
colorHexMap.set('white', '#FFFFFF');
colorHexMap.set('black', '#000000');
for(const [color, hex] of colorHexMap) {
console.log(color, hex);
}
//'white' '#FFFFFF' 'black' '#000000'
นอกจากนี้ map.keys () จะส่งคืนตัววนซ้ำผ่านคีย์และ map.values () จะส่งคืนตัววนซ้ำตามค่าด้วย
4. เราสามารถทราบขนาดของแผนที่ได้อย่างง่ายดาย
เราไม่สามารถกำหนดจำนวนคุณสมบัติโดยตรงในวัตถุธรรมดา เราต้องการตัวช่วย fn เช่น Object.keys () ซึ่งคืนค่าอาเรย์ด้วยปุ่มของวัตถุจากนั้นใช้คุณสมบัติความยาวเราสามารถรับจำนวนของคีย์หรือขนาดของวัตถุธรรมดา
const exams= {'John Rambo': '80%', 'James Bond': '60%'};
const sizeOfObj= Object.keys(exams).length;
console.log(sizeOfObj); // 2
แต่ในกรณีของแผนที่เราสามารถเข้าถึงขนาดแผนที่ได้โดยตรงโดยใช้คุณสมบัติ map.size
const examsMap= new Map([['John Rambo', '80%'], ['James Bond', '60%']]);
console.log(examsMap.size);