ขอบเขตตัวแปรใน TypeScript: การเข้าใจ ‘Scope’ อย่างลึกซึ้ง
สำหรับนักพัฒนาที่ทำงานกับ JavaScript หรือ TypeScript ได้อย่างมืออาชีพแล้ว คำว่า “Variable Scopes” คงไม่ใช่เรื่องแปลกใหม่ แต่การทำความเข้าใจกลไกเบื้องหลังของมัน—โดยเฉพาะแนวคิดเชิงทฤษฎีอย่าง Lexical Scope—คือสิ่งที่แยกโค้ดที่ดีออกจากโค้ดที่มีบั๊กยากต่อการแก้ไข บทความนี้จะเจาะลึกถึงหลักการเหล่านี้ เพื่อให้คุณสามารถจัดการและคาดการณ์พฤติกรรมของตัวแปรได้อย่างแม่นยำ
1. สภาพจำเพาะของการกำหนดขอบเขต (Scoping Rules)
พื้นฐานที่สุด, scope คือบริเวณหรือบริบทที่เราประกาศใช้งานชื่อ identifier ตัวผังภาษาเช่น Python มีระบบ scoping ที่ชัดเจน ขณะที่โลกของ JS/TS จะมีการเปลี่ยนแปลงตาม Keyword และ Context:
- Global Scope: เป็นขอบเขตสูงสุด ข้อมูลใดๆ ถูกนิยามไว้ที่นี่จะมีผลกระทบครอบคลุมทั่วทั้งโปรแกรม ซึ่งเป็นสาเหตุอันดับต้น ๆ ของปัญหา Name Collision
- extbf{Function Scope:} ก่อนยุค ES6 การใช้ `var` ทำให้เกิด Function Scope หมายความว่าตัวแปรนั้นมองเห็นได้ตลอดภายในฟังก์ชัน ไม่ว่าจะถูกเรียกจากส่วนไหนก็ตาม
- extbf{Block Scope:** นับตั้งแต่แนะนำ Keywords อย่าง `let` และ `const`, JavaScript ได้นำ Block Scoping เข้ามาบังคับใช้อย่างเคร่งครัด นี่คือจุดเปลี่ยนสำคัญ เพราะมันทำให้วงเล็บปีกกา `{}` สามารถสร้างพื้นที่เฉพาะสำหรับกลุ่มคำสั่งได้จริง เช่น ในลูป (`for`) หรือเงื่อนไข (`if`).
2. เจาะหลักการ Lexical Scope (Scope ตามโครงร่างโค้ด)
ถ้าหาก Variable Scope บอกเราแค่ ‘ตรงนี้ถึงเมื่อไหร่’ ล่ะ? ส่วน Lexical Scope คือกลไกทางภาษาศาสตร์คอมพิวเตอร์ ที่บอกเราว่า **‘จะหาค่าของชื่อ variable นี้ได้อย่างไร?’**
Lexical scope ยืนอยู่บนสมมติฐานที่เรียกว่า