Guest Adventurer 🥉 Lv.1
🪙 50
🔷 10
← Back to library
Article · programming

JavaScript: Object และข้อมูลแบบ Key-Value

JavaScript

EP8 ของชุด JavaScript คืออะไร? เริ่มต้นเขียนโปรแกรม เรียนรู้ Object, properties, methods, การเข้าถึงและแก้ไขข้อมูล การวนลูป Object และการทำงานร่วมกับ Array เพื่อสร้างข้อมูลสำหรับระบบจริง

EP8: จัดเก็บข้อมูลอย่างเป็นระบบด้วย Object

ใน EP7 เราเรียนรู้ Array ซึ่งเหมาะกับการเก็บข้อมูลหลายรายการตามลำดับ แต่เมื่อข้อมูลหนึ่งรายการมีรายละเอียดหลายด้าน เช่น สินค้าที่มีรหัส ชื่อ ราคา และจำนวนคงเหลือ เราจำเป็นต้องมีโครงสร้างที่เชื่อมโยงชื่อคุณสมบัติกับค่าได้โดยตรง JavaScript จึงมี **Object** สำหรับเก็บข้อมูลในรูปแบบ Key-Value ทำให้เราสามารถอ้างอิงข้อมูลด้วยชื่อคุณสมบัติ อ่านและแก้ไขค่า เพิ่มข้อมูลใหม่ รวมถึงสร้างฟังก์ชันที่ทำงานร่วมกับข้อมูลนั้นได้
ตัวอย่างการเขียนโปรแกรมบนหน้าจอคอมพิวเตอร์
Object ช่วยจัดกลุ่มคุณสมบัติของข้อมูลให้อยู่ในโครงสร้างเดียวกัน

1. Object คืออะไร

Object คือโครงสร้างข้อมูลที่เก็บคุณสมบัติเป็นคู่ Key-Value โดย Key เรียกว่า property name และ Value คือค่าที่สัมพันธ์กับ Key นั้น ตัวอย่างเช่น Object ของนักเรียนอาจมีชื่อ อายุ และระดับชั้น ส่วน Object ของสินค้าอาจมีรหัส ชื่อ ราคา และจำนวนคงเหลือ
const student = {
    name: 'Mali',
    age: 12,
    grade: 'ม.1'
};

console.log(student.name);
console.log(student.age);
console.log(student.grade);

// ผลลัพธ์:
// Mali
// 12
// ม.1
ในตัวอย่าง `name`, `age` และ `grade` คือ Key ส่วน `'Mali'`, `12` และ `'ม.1'` คือ Value หาก Key เป็นชื่อที่เขียนได้ตามรูปแบบ Identifier ของ JavaScript สามารถใช้ชื่อโดยไม่ใส่เครื่องหมายคำพูดได้ แต่หากชื่อมีช่องว่างหรือเป็นข้อความที่ไม่ใช่ Identifier ตามปกติ ต้องเขียน Key เป็น String ภายในเครื่องหมายคำพูด
แนวคิดสำคัญArray เน้นจัดเก็บสมาชิกตามลำดับและเข้าถึงด้วย index ส่วน Object เน้นจัดเก็บค่าที่มีชื่อคุณสมบัติกำกับ จึงเหมาะกับข้อมูลที่มีรายละเอียดหลายด้าน

2. สร้าง Object และกำหนด Properties

เราสามารถสร้าง Object ด้วยเครื่องหมายปีกกา `{}` แล้วกำหนด Key และ Value โดยใช้เครื่องหมายโคลอนคั่นระหว่างกัน และใช้เครื่องหมายจุลภาคคั่นแต่ละ Property ค่าใน Object สามารถเป็น String, Number, Boolean, Array, Object ซ้อนกัน หรือฟังก์ชันก็ได้
const product = {
    id: 101,
    name: 'Wireless Mouse',
    price: 450,
    inStock: true,
    tags: ['computer', 'accessory'],
    supplier: {
        name: 'Tech Supply',
        country: 'Thailand'
    }
};

console.log(product.name);
console.log(product.tags[0]);
console.log(product.supplier.name);

// ผลลัพธ์:
// Wireless Mouse
// computer
// Tech Supply
ตัวอย่างนี้แสดงให้เห็นว่า Object สามารถเก็บ Array และ Object ซ้อนอยู่ภายในได้ การเข้าถึงข้อมูลที่ซ้อนกันทำได้ด้วยการต่อจุด เช่น `product.supplier.name` ส่วนสมาชิกภายใน Array เข้าถึงด้วย index เช่น `product.tags[0]`

3. เข้าถึงข้อมูลด้วย Dot Notation และ Bracket Notation

JavaScript มีวิธีเข้าถึง Property ที่ใช้บ่อยสองแบบ ได้แก่ Dot Notation เช่น `product.name` และ Bracket Notation เช่น `product['name']` ทั้งสองแบบสามารถอ่านค่าของ Property ได้ แต่ Bracket Notation เหมาะกับกรณีที่ชื่อ Key มีช่องว่างหรือชื่อ Key มาจากตัวแปร
const customer = {
    name: 'Anan',
    'member level': 'Gold',
    city: 'Bangkok'
};

const propertyName = 'city';

console.log(customer.name);
console.log(customer['member level']);
console.log(customer[propertyName]);

// ผลลัพธ์:
// Anan
// Gold
// Bangkok
เมื่อใช้ `customer[propertyName]` JavaScript จะนำค่าของตัวแปร `propertyName` มาใช้เป็น Key ในตัวอย่างนี้จึงอ่าน `customer.city` ได้ แต่ถ้าเขียน `customer.propertyName` โปรแกรมจะค้นหา Property ที่ชื่อ `propertyName` โดยตรง ซึ่งไม่ใช่สิ่งเดียวกัน
ข้อผิดพลาดที่พบบ่อยหากชื่อ Property มาจากตัวแปร ให้ใช้วงเล็บเหลี่ยม เช่น `object[key]` ไม่ใช่ `object.key` เพราะ Dot Notation จะใช้คำหลังจุดเป็นชื่อ Property แบบตรงตัว

4. เพิ่ม แก้ไข และลบ Properties

Object ที่ประกาศด้วย `const` ยังสามารถเปลี่ยนแปลง Property ได้ `const` ป้องกันการกำหนดตัวแปรให้ชี้ไปยัง Object ตัวใหม่ แต่ไม่ได้ทำให้ข้อมูลภายใน Object กลายเป็นข้อมูลที่แก้ไขไม่ได้ เราสามารถกำหนด Property ใหม่ เปลี่ยนค่าเดิม หรือลบ Property ด้วย `delete` ได้
const account = {
    username: 'mali12',
    points: 100
};

account.points = 150;
account.email = '[email protected]';
delete account.username;

console.log(account);
console.log(account.points);

// ผลลัพธ์:
// { points: 150, email: '[email protected]' }
// 150
การใช้ `delete` จะนำ Property ออกจาก Object แต่หากต้องการเก็บ Key ไว้และเปลี่ยนค่าเป็น `null` หรือ `undefined` ต้องกำหนดค่าใหม่แทน การเลือกวิธีขึ้นอยู่กับความหมายของข้อมูลและข้อกำหนดของระบบ

5. ตรวจสอบว่ามี Property อยู่หรือไม่

การอ่าน Property ที่ไม่มีอยู่มักคืนค่า `undefined` หากต้องการตรวจสอบการมีอยู่ของ Key สามารถใช้ตัวดำเนินการ `in` ซึ่งตรวจสอบทั้ง Property ของ Object และ Property ที่สืบทอดมาจาก Prototype หรือใช้ `Object.hasOwn()` เมื่อต้องการตรวจสอบเฉพาะ Property ที่ Object นั้นเป็นเจ้าของเอง
const profile = {
    name: 'Niran',
    nickname: undefined
};

console.log(profile.name);
console.log(profile.email);
console.log('email' in profile);
console.log(Object.hasOwn(profile, 'name'));
console.log(Object.hasOwn(profile, 'nickname'));

// ผลลัพธ์:
// Niran
// undefined
// false
// true
// true
จุดที่ควรจำคือ Property ที่มีอยู่แต่มีค่าเป็น `undefined` แตกต่างจาก Property ที่ไม่มีอยู่เลย ในตัวอย่าง `nickname` เป็น Property ที่มีอยู่จริง แม้ค่าจะเป็น `undefined` ขณะที่ `email` ไม่ได้ถูกกำหนดไว้ใน Object

6. Methods: ฟังก์ชันภายใน Object

เมื่อ Property ของ Object เก็บฟังก์ชัน เรามักเรียกฟังก์ชันนั้นว่า Method Method ช่วยรวมข้อมูลกับพฤติกรรมที่เกี่ยวข้องไว้ในโครงสร้างเดียวกัน เช่น Object ของตะกร้าสินค้าอาจมีรายการสินค้าและมี Method สำหรับคำนวณยอดรวม
const cart = {
    items: [
        { name: 'Keyboard', price: 1200, quantity: 1 },
        { name: 'Mouse', price: 450, quantity: 2 }
    ],
    getTotal() {
        return this.items.reduce(
            (total, item) => total + item.price * item.quantity,
            0
        );
    }
};

console.log(cart.getTotal());

// ผลลัพธ์:
// 2100
คำว่า `this` ใน Method ตัวอย่างนี้หมายถึง Object ที่ใช้เรียก Method ผ่าน `cart.getTotal()` จึงสามารถอ่าน `cart.items` ผ่าน `this.items` ได้ อย่างไรก็ตาม ความหมายของ `this` ขึ้นอยู่กับวิธีเรียกฟังก์ชันและรูปแบบฟังก์ชันด้วย จึงควรเรียนรู้บริบทของ `this` ให้ละเอียดเมื่อเขียนโปรแกรมที่ซับซ้อนขึ้น
คำนวณยอดรวมอย่างไรแต่ละรายการมีมูลค่าเท่ากับ price คูณ quantity จากนั้น reduce จะรวมมูลค่าทุกชิ้นเข้าด้วยกัน Keyboard ราคา 1,200 บาท จำนวน 1 ชิ้น และ Mouse ราคา 450 บาท จำนวน 2 ชิ้น รวมเป็น 2,100 บาท

7. วนลูปอ่าน Properties ด้วย Object.keys, values และ entries

JavaScript มีเมธอดช่วยดึงข้อมูลจาก Object ได้แก่ `Object.keys()` สำหรับรายการ Key, `Object.values()` สำหรับรายการ Value และ `Object.entries()` สำหรับคู่ Key-Value ในรูปแบบ Array ของ Array แต่ละเมธอดจะคืน Array ใหม่ ทำให้สามารถนำผลลัพธ์ไปวนลูปหรือใช้เมธอด Array ต่อได้
const stock = {
    keyboard: 8,
    mouse: 12,
    monitor: 5
};

console.log(Object.keys(stock));
console.log(Object.values(stock));
console.log(Object.entries(stock));

for (const [name, quantity] of Object.entries(stock)) {
    console.log(`${name}: ${quantity} ชิ้น`);
}

// ผลลัพธ์:
// ['keyboard', 'mouse', 'monitor']
// [8, 12, 5]
// [['keyboard', 8], ['mouse', 12], ['monitor', 5]]
// keyboard: 8 ชิ้น
// mouse: 12 ชิ้น
// monitor: 5 ชิ้น
การใช้ `Object.entries()` ร่วมกับ `for...of` ช่วยให้เข้าถึง Key และ Value พร้อมกันได้ ส่วนรูปแบบ `[name, quantity]` เรียกว่า Destructuring Assignment ซึ่งจะแยกสมาชิกสองตัวในแต่ละคู่มาเก็บในตัวแปรตามลำดับ

8. เปรียบเทียบ Object กับ Array

ประเด็นArrayObject
โครงสร้างสมาชิกเรียงตามลำดับข้อมูลในรูปแบบ Key-Value
วิธีเข้าถึงทั่วไปใช้ index เช่น items[0]ใช้ชื่อ Property เช่น user.name
เหมาะกับรายการข้อมูลหลายรายการข้อมูลหนึ่งรายการที่มีหลายคุณสมบัติ
การวนลูปfor...of, forEach, mapObject.keys, Object.values, Object.entries
ตัวอย่างรายการสินค้าในตะกร้ารายละเอียดสินค้าหนึ่งรายการ
ในระบบจริง Array และ Object มักทำงานร่วมกัน โดย Array เก็บรายการสินค้าหลายรายการ และ Object แทนรายละเอียดของสินค้าแต่ละรายการ การออกแบบเช่นนี้ช่วยให้การค้นหา การแสดงผล และการคำนวณทำได้เป็นขั้นตอน

9. รวม Array กับ Object เพื่อจัดการรายการสินค้า

ตัวอย่างต่อไปนี้จำลองข้อมูลสินค้าในร้านค้า โดยแต่ละสินค้าเป็น Object และสินค้าทั้งหมดถูกจัดเก็บใน Array จากนั้นใช้ `filter()` เพื่อคัดสินค้าที่มีสต็อก ใช้ `map()` เพื่อสร้างรายการแสดงผล และใช้ `reduce()` เพื่อคำนวณมูลค่าสต็อกรวม
const products = [
    { id: 1, name: 'Keyboard', price: 1200, stock: 8 },
    { id: 2, name: 'Mouse', price: 450, stock: 0 },
    { id: 3, name: 'Monitor', price: 5200, stock: 5 },
    { id: 4, name: 'Webcam', price: 890, stock: 3 }
];

const availableProducts = products.filter(product => product.stock > 0);

const displayList = availableProducts.map(product => ({
    name: product.name,
    stock: product.stock
}));

const totalValue = availableProducts.reduce(
    (sum, product) => sum + product.price * product.stock,
    0
);

console.log(displayList);
console.log(totalValue);

// มูลค่าสต็อกรวม:
// 38270
มูลค่าสต็อกรวมคำนวณจากราคาต่อหน่วยคูณจำนวนคงเหลือของแต่ละสินค้า Keyboard มีมูลค่า 9,600 บาท Monitor มีมูลค่า 26,000 บาท และ Webcam มีมูลค่า 2,670 บาท รวมเป็น 38,270 บาท Mouse ถูกตัดออกจากการคำนวณเพราะมีสต็อกเป็นศูนย์

10. คัดลอก Object ด้วย Spread Syntax

Spread Syntax (`...`) สามารถใช้สร้าง Object ใหม่โดยคัดลอก Property ที่แจงนับได้จาก Object เดิม และยังใช้รวมข้อมูลจากหลาย Object ได้ วิธีนี้เหมาะกับการสร้างข้อมูลฉบับปรับปรุงโดยไม่เปลี่ยน Property ระดับแรกของ Object ต้นฉบับ
const originalUser = {
    name: 'Mali',
    role: 'member',
    active: true
};

const updatedUser = {
    ...originalUser,
    role: 'admin',
    city: 'Bangkok'
};

console.log(originalUser);
console.log(updatedUser);

// originalUser ยังคง role เป็น member
// updatedUser มี role เป็น admin และ city เป็น Bangkok
เมื่อ Key ซ้ำกันใน Object ที่สร้างจาก Spread Syntax ค่าที่กำหนดทีหลังจะเขียนทับค่าก่อนหน้าใน Object ผลลัพธ์ ดังนั้นการวาง `role: 'admin'` หลัง `...originalUser` จึงทำให้ `updatedUser.role` เป็น `admin` โดยไม่เปลี่ยน `originalUser.role`
Shallow Copy ไม่ใช่ Deep CopySpread Syntax คัดลอกเฉพาะระดับแรก หาก Object มี Array หรือ Object ซ้อนอยู่ภายใน ค่าที่ซ้อนกันยังอาจอ้างอิงข้อมูลชุดเดิมอยู่ หากต้องการแยกข้อมูลซ้อนอย่างแท้จริง ต้องเลือกวิธีคัดลอกให้เหมาะกับชนิดข้อมูลและสภาพแวดล้อมที่ใช้งาน

11. ใช้ Optional Chaining และ Nullish Coalescing

ข้อมูลจาก API หรือฐานข้อมูลอาจมีบาง Property ที่ไม่มีอยู่ การเข้าถึง Property ซ้อนกันโดยไม่ตรวจสอบอาจทำให้เกิด TypeError หากค่าระดับกลางเป็น `null` หรือ `undefined` Optional Chaining (`?.`) ช่วยให้อ่าน Property อย่างปลอดภัยขึ้น ส่วน Nullish Coalescing (`??`) ใช้กำหนดค่าเริ่มต้นเมื่อค่าด้านซ้ายเป็น `null` หรือ `undefined`
const order = {
    id: 5001,
    customer: {
        name: 'Anan'
    }
};

const customerName = order.customer?.name ?? 'ไม่ระบุชื่อ';
const shippingCity = order.shipping?.city ?? 'ยังไม่มีข้อมูลที่อยู่';

console.log(customerName);
console.log(shippingCity);

// ผลลัพธ์:
// Anan
// ยังไม่มีข้อมูลที่อยู่
ควรแยกความแตกต่างระหว่าง `??` กับ `||` เพราะ `||` จะใช้ค่าเริ่มต้นเมื่อค่าด้านซ้ายเป็น Falsy เช่น 0, false หรือ String ว่าง แต่ `??` จะใช้ค่าเริ่มต้นเฉพาะ `null` และ `undefined` จึงเหมาะเมื่อค่าศูนย์หรือ false เป็นข้อมูลที่ถูกต้อง
const stockCount = 0;

console.log(stockCount || 10);
console.log(stockCount ?? 10);

// ผลลัพธ์:
// 10
// 0

12. Object กับ JSON ต่างกันอย่างไร

Object เป็นโครงสร้างข้อมูลที่ใช้ภายใน JavaScript ส่วน JSON เป็นรูปแบบข้อความมาตรฐานสำหรับแลกเปลี่ยนข้อมูลระหว่างระบบ JSON มีกฎรูปแบบเข้มงวดกว่า Object Literal เช่น Key และ String ต้องใช้เครื่องหมายคำพูดคู่ และ JSON ไม่รองรับฟังก์ชันหรือค่า `undefined` โดยตรง
const user = {
    id: 101,
    name: 'Mali',
    active: true
};

const jsonText = JSON.stringify(user);
const parsedUser = JSON.parse(jsonText);

console.log(jsonText);
console.log(parsedUser.name);

// ผลลัพธ์:
// {"id":101,"name":"Mali","active":true}
// Mali
`JSON.stringify()` แปลงข้อมูลที่รองรับให้เป็นข้อความ JSON ส่วน `JSON.parse()` แปลงข้อความ JSON ที่ถูกต้องกลับเป็นค่าของ JavaScript หากข้อความไม่ใช่ JSON ที่ถูกต้อง `JSON.parse()` จะเกิดข้อผิดพลาด จึงควรตรวจสอบแหล่งข้อมูลและจัดการข้อผิดพลาดเมื่อรับข้อมูลจากภายนอก
ความปลอดภัยของข้อมูลอย่าใช้ JSON.parse() กับข้อความที่ไม่น่าเชื่อถือโดยไม่จัดการข้อผิดพลาด และอย่าเชื่อถือข้อมูลจากผู้ใช้หรือ API เพียงเพราะข้อมูลอยู่ในรูปแบบ JSON ควรตรวจสอบชนิดข้อมูล รูปแบบ และสิทธิ์การใช้งานก่อนนำไปประมวลผล

13. คำนวณคะแนนรวมจาก Object

ลองใช้ Object เก็บคะแนนของนักเรียนแต่ละวิชา แล้วแปลงค่าคะแนนให้เป็น Array ด้วย `Object.values()` ก่อนคำนวณผลรวมและค่าเฉลี่ย วิธีนี้ช่วยให้เราแยกข้อมูลที่มีชื่อวิชาออกจากกระบวนการคำนวณได้อย่างชัดเจน
const scores = {
    mathematics: 85,
    science: 92,
    english: 78,
    programming: 95
};

const values = Object.values(scores);
const total = values.reduce((sum, score) => sum + score, 0);
const average = values.length > 0 ? total / values.length : 0;

console.log('คะแนนรวม:', total);
console.log('ค่าเฉลี่ย:', average);
console.log('วิชาที่ได้คะแนนสูงสุด:', Object.entries(scores)
    .reduce((best, current) => current[1] > best[1] ? current : best)[0]);

// ผลลัพธ์:
// คะแนนรวม: 350
// ค่าเฉลี่ย: 87.5
// วิชาที่ได้คะแนนสูงสุด: programming
ตัวอย่างนี้ใช้ `Object.entries()` เพื่อให้ได้คู่ชื่อวิชาและคะแนน จากนั้น reduce จะเปรียบเทียบคะแนนของแต่ละวิชาเพื่อเก็บคู่ที่มีคะแนนสูงที่สุดไว้ หากต้องการให้โปรแกรมรองรับ Object ว่าง ควรตรวจสอบว่ามีข้อมูลก่อนค้นหาค่าสูงสุด

14. สรุปแนวคิดและข้อควรระวัง

แนวคิดสิ่งที่ควรจำตัวอย่าง
สร้าง Objectใช้วงเล็บปีกกาและกำหนด Key-Valueconst user = { name: 'Mali' }
อ่าน Propertyใช้จุดหรือวงเล็บเหลี่ยมuser.name
ใช้ Key จากตัวแปรใช้ Bracket Notationuser[key]
เพิ่มหรือแก้ไขข้อมูลกำหนดค่าให้ Propertyuser.active = true
ตรวจสอบ Property ของตัวเองใช้ Object.hasOwn()Object.hasOwn(user, 'name')
ดึง Key และ Valueใช้ Object.keys(), values(), entries()Object.entries(user)
คัดลอก Object ระดับแรกใช้ Spread Syntax{ ...user, active: false }
จัดการ Property ที่อาจไม่มีใช้ ?. และ ?? ตามความเหมาะสมuser.profile?.city ?? 'ไม่ระบุ'

15. แบบฝึกหัดท้ายบท

สร้าง Object ชื่อ `book` ที่มีคุณสมบัติ `title`, `author`, `price` และ `inStock` จากนั้นทำภารกิจต่อไปนี้: แสดงชื่อหนังสือ เปลี่ยนราคา เพิ่ม Property ชื่อ `category` ตรวจสอบว่ามี Property `author` อยู่หรือไม่ และสร้าง Object ใหม่ที่เปลี่ยน `inStock` เป็น false โดยไม่แก้ไข Object ต้นฉบับ
เฉลยข้อ 1: สร้าง Object และอ่านชื่อหนังสือ
กำหนด `const book = { title: 'JavaScript Basics', author: 'Mali', price: 320, inStock: true };` จากนั้นอ่านชื่อด้วย `console.log(book.title)`
เฉลยข้อ 2: แก้ไขราคาและเพิ่มหมวดหมู่
ใช้ `book.price = 350` เพื่อเปลี่ยนราคา และ `book.category = 'Programming'` เพื่อเพิ่ม Property ใหม่
เฉลยข้อ 3: ตรวจสอบ Property
ใช้ `Object.hasOwn(book, 'author')` จะได้ `true` เพราะ Object มี Property ชื่อ author อยู่จริง
เฉลยข้อ 4: สร้าง Object ใหม่โดยคงต้นฉบับ
ใช้ `const updatedBook = { ...book, inStock: false };` วิธีนี้สร้าง Object ใหม่และเปลี่ยนค่า inStock ในผลลัพธ์ โดยไม่เปลี่ยนค่า inStock ของ book ต้นฉบับ

16. เตรียมพร้อมสำหรับ EP9

ตอนนี้คุณรู้จักการใช้ Object เพื่อจัดกลุ่มข้อมูลตามชื่อ Property และสามารถทำงานร่วมกับ Array เพื่อสร้างรายการข้อมูลที่ใกล้เคียงกับระบบจริงได้แล้ว ใน EP9 เราจะต่อยอดสู่ Functions อย่างเป็นระบบ ตั้งแต่การประกาศฟังก์ชัน การส่ง Parameters การคืนค่าด้วย return ไปจนถึง Arrow Functions และการแยกโค้ดออกเป็นส่วนที่นำกลับมาใช้ซ้ำได้
โครงสร้างข้อมูลที่ดีช่วยให้โปรแกรมไม่เพียงทำงานได้ แต่ยังทำให้คนอื่นอ่าน เข้าใจ และพัฒนาต่อได้ง่ายขึ้น
เป้าหมายก่อนเรียนตอนถัดไปลองสร้าง Array ที่มี Object สินค้าอย่างน้อย 3 รายการ แล้วฝึกอ่านชื่อ เปลี่ยนราคา คัดกรองสินค้าที่มีสต็อก และรวมมูลค่าสต็อกด้วย reduce เมื่อทำได้คล่อง คุณพร้อมต่อยอดไปสู่การเขียน Functions แล้ว
Reach within 500px of the page end and stay for at least 5 minutes to earn EXP once per day.

⏳ Reading timer is running...

🌐
Select Language
21 World Languages Supported