Fundamentals
Data types (string, number, boolean, null, undefined)
แยกแยะชนิดข้อมูลพื้นฐานทั้งเจ็ดของ JavaScript พร้อมใช้ `typeof` ตรวจชนิด และรู้ว่า Symbol กับ BigInt ต่างจากชนิดอื่นตรงไหน ผ่านโจทย์ที่ไล่ระดับ
1) ปัญหา: บวกเลขแล้วได้ข้อความ
ร้านค้าแห่งหนึ่งรับราคาสินค้าจากแบบฟอร์มแล้วนำมาคำนวณยอดรวม โปรแกรมทำงานได้ไม่ error แต่ผลลัพธ์ที่ได้กลับกลายเป็นข้อความยาว ๆ แทนที่จะเป็นตัวเลข สาเหตุคือค่าที่รับมาไม่ได้เป็นตัวเลขเสมอไป JavaScript จะตัดสินใจจาก "ชนิดข้อมูล" ของค่าที่เจอ ถ้าฝั่งหนึ่งเป็นข้อความ การบวกจะกลายเป็นการต่อข้อความทันที
บรรทัดแรกบวกเลขได้ 10 ส่วนบรรทัดที่สองต่อข้อความจนได้ 55
ทายก่อน: ทำไม `5 + 5` ได้ 10 แต่ `"5" + 5` ได้ "55"?
2) ชนิดข้อมูลคือป้ายบอกว่าค่าคืออะไร
ทุกค่าใน JavaScript มีชนิดข้อมูล (data type) กำกับอยู่เสมอ ชนิดบอกว่าค่านั้นเป็นตัวเลข ข้อความ ค่าจริง/เท็จ หรือค่าพิเศษอื่น ๆ และเป็นตัวกำหนดว่า JavaScript จะทำอะไรกับค่าได้บ้าง ค่าพื้นฐานที่สุดเรียกว่า primitive type เป็นค่าชิ้นเดียว ไม่ใช่โครงสร้างที่ซ้อนกัน JavaScript มี primitive ทั้งหมด 7 ชนิด
| ชนิด | ตัวอย่างค่า | ใช้เก็บอะไร |
|---|---|---|
| string | "สวัสดี", 'Hello' | ข้อความ ชื่อ ที่อยู่ |
| number | 42, 3.14, -7 | ตัวเลขทั้งหมด ทั้งจำนวนเต็มและทศนิยม |
| boolean | true, false | ค่าจริง/เท็จ สถานะ เงื่อนไข |
| null | null | ว่างเปล่าโดยเจตนา — เราตั้งเองว่าไม่มีค่า |
| undefined | undefined | ยังไม่ได้กำหนดค่า — ค่าเริ่มต้นของตัวแปรใหม่ |
| symbol | Symbol("id") | ค่าเฉพาะที่ไม่ซ้ำกับใคร |
| bigint | 9007199254740993n | จำนวนเต็มขนาดใหญ่มาก |
ชนิดแรก ๆ อย่าง string, number, boolean, null และ undefined จะถูกเจาะลึกอีกครั้งใน phase ถัดไป ส่วน symbol และ bigint มีจุดใช้เฉพาะ — บทนี้ให้ภาพรวมที่เพียงพอต่อการใช้งานทั่วไป
3) `typeof` — ถามว่าค่าหนึ่งมีชนิดอะไร
`typeof` เป็น operator ที่ตอบคำถามว่า "ค่านี้เป็นชนิดอะไร" ผลลัพธ์เป็นข้อความ เช่น "string", "number", "boolean" มีจุดที่ต้องจำหนึ่งอย่าง: `typeof null` คืนค่า "object" ซึ่งเป็นบั๊กเก่าตั้งแต่ยุคแรกของ JavaScript และยังคงอยู่เพื่อไม่ให้โค้ดเก่าพัง
ผลลัพธ์ของ typeof เป็นข้อความเสมอ
4) string, number และ boolean ในโค้ดจริง
ในโค้ดจริงเราเก็บค่าต่างชนิดไว้ในตัวแปรและแสดงผลร่วมกันได้ สังเกตว่าข้อความต้องอยู่ในเครื่องหมายคำพูดเสมอ ส่วนตัวเลขและค่าจริง/เท็จเขียนตรง ๆ ได้เลย
ชื่อและข้อความใช้ string, ราคาและจำนวนใช้ number, สถานะใช้ boolean
5) null กับ undefined ต่างกันที่เจตนา
ทายก่อน: ถ้าประกาศ `let profilePicture;` แล้วไม่กำหนดค่าเลย ตัวแปรนี้จะมีค่าอะไร?
`null` คือ "ไม่มีค่า และเราตั้งใจให้เป็นแบบนั้น" ส่วน `undefined` คือ "ยังไม่เคยถูกกำหนดค่า" ซึ่ง JavaScript ใส่ให้เองเมื่อประกาศตัวแปรแล้วไม่กำหนดอะไร ความต่างนี้สำคัญตอนอ่านโค้ด: เจอ `null` แปลว่ามีคนตั้งใจล้างค่า เจอ `undefined` แปลว่าอาจลืมกำหนดค่า
null มาจากการตั้งใจ ส่วน undefined มาจากการยังไม่กำหนด
6) symbol — ค่าเฉพาะที่ไม่ซ้ำกับใคร
`symbol` ใช้สร้างค่าใหม่ที่ไม่ซ้ำกับค่าใดในโปรแกรม ทุกครั้งที่เรียก `Symbol()` จะได้ค่าใหม่เสมอ แม้คำอธิบายในวงเล็บจะเขียนเหมือนกัน คำอธิบาย (description) มีไว้ให้เราอ่านและ debug เท่านั้น ไม่ได้ทำให้ symbol สองตัวเท่ากัน ใช้ `symbol` เมื่อต้องการค่าเฉพาะจริง ๆ
ทั้งคู่มี description เป็น id แต่เป็นคนละค่า เพราะ Symbol() สร้างค่าใหม่ทุกครั้ง
ในงานจริง symbol มักถูกใช้เป็น key เฉพาะของ object เพื่อไม่ให้ชื่อชนกับ key อื่น — รายละเอียดเรื่อง object จะเรียนในบทหลังจากนี้ บทนี้ให้จำแค่ว่า symbol สร้าง "ค่าเฉพาะ" ที่ไม่มีใครซ้ำ
7) bigint — จำนวนเต็มที่ number เก็บไม่ไหว
`number` เก็บจำนวนเต็มได้แม่นยำจำกัด ไม่เกินค่าที่ JavaScript กำหนดไว้ เกินจากนี้ผลลัพธ์จะเริ่มคลาดเคลื่อน โดยเฉพาะเมื่อนำไปคำนวณต่อ `bigint` ถูกสร้างมาเพื่อจำนวนเต็มขนาดใหญ่มาก เขียนโดยเติม `n` ต่อท้ายจำนวนเต็ม เช่น `9007199254740993n` และคำนวณกับ bigint ด้วยกันได้
การบวก 1 กับ 2 ให้ผลเท่ากันเพราะ number เก็บค่าที่เกินขอบเขตไม่ไหว ส่วน bigint แม่นยำ
ข้อควรจำ: bigint คำนวณปนกับ number โดยตรงไม่ได้ ถ้าค่าอยู่คนละชนิด JavaScript จะหยุดด้วย error จึงควรเลือกใช้ชนิดเดียวกันตั้งแต่ต้น
ทายก่อน: `9007199254740991 + 2` ให้ผลเท่าไร และตรงกับที่คาดไว้หรือไม่?
8) ตรวจชนิดก่อนคำนวณเสมอ
ทายก่อน: จากสองแบบนี้ แบบไหนคำนวณได้ตามคาด และแบบไหนทำให้โปรแกรมหยุด?
ผสม bigint กับ number ไม่ได้
JavaScript หยุดด้วย TypeError เพราะค่านับจำนวนกับค่าทศนิยมคนละชนิดกัน
ใช้ชนิดเดียวกันทั้งสองฝั่ง ผลลัพธ์จึงออกมาถูกต้อง
สามคำถามก่อนเดาชนิดของค่า
ค่านี้อยู่ในเครื่องหมายคำพูดหรือไม่
ถ้าอยู่ในเครื่องหมายคำพูด ชนิดคือ string ทันที แม้ข้างในจะดูเป็นตัวเลข
ค่านี้ควรเป็นตัวเลขหรือค่าจริง/เท็จ
ตัวเลขไม่ต้องมีเครื่องหมายคำพูด ส่วน boolean เขียนได้แค่ true กับ false
ค่าคือความว่างแบบไหน
ตั้งใจว่างใช้ `null` ยังไม่กำหนดค่าใช้ `undefined` — และ `typeof null` คืน "object" เสมอ
Lab 1: ประกาศตัวแปรสี่ชนิด
Lab 2: อ่านชนิดด้วย `typeof`
Lab 3: ความว่างสองแบบ
Lab 4: symbol สองตัวที่ไม่ซ้ำกัน
Lab 5: bigint สำหรับตัวเลขขนาดใหญ่
Lab 6: ซ่อมชนิดข้อมูลที่ผิด
Lab 7: ประกอบผลลัพธ์ครบทุกชนิด
สรุปและก้าวต่อไป
- ทุกค่ามีชนิดข้อมูล และชนิดคือตัวกำหนดว่าคำนวณหรือใช้ค่านั้นได้อย่างไร
- primitive มี 7 ชนิด: string, number, boolean, null, undefined, symbol และ bigint
- `typeof` ใช้ถามชนิดของค่า แต่ `typeof null` คืน "object" เป็นบั๊กเก่าที่ต้องจำ
- `null` คือว่างโดยเจตนา ส่วน `undefined` คือยังไม่ถูกกำหนดค่า
- `symbol` สร้างค่าใหม่ที่ไม่ซ้ำกับใคร แม้คำอธิบายจะเหมือนกัน
- `bigint` เก็บจำนวนเต็มขนาดใหญ่มากด้วยการเติม `n` และห้ามคำนวณปนกับ number
- ก้าวต่อไป: เรียน Expressions vs Statements (expressions-vs-statements) เพื่อแยกให้ออกว่าโค้ดส่วนไหนให้ค่า และส่วนไหนเป็นคำสั่ง