การเลือกใช้ระหว่าง var, let, และ const ใน JavaScript

การเลือกใช้ระหว่าง var, let, และ const มีผลต่อความชัดเจน ความปลอดภัย และบั๊กของโค้ดคุณ โดยทั้งสามต่างกันที่ “ขอบเขตการมองเห็น (scope)”, “พฤติกรรมการ hoist”, และ “กฎการประกาศซ้ำ/แก้ค่า”.

ขอบเขต (scope)

  • var: มีขอบเขตแบบฟังก์ชัน (function scope) หรือโกลบอล หากประกาศนอกฟังก์ชันจะเป็นตัวแปรโกลบอล และ var ไม่เคารพขอบเขตบล็อก { } เช่นใน if/for ตัวแปรยังมองเห็นได้นอกบล็อกนั้น.
  • let / const: มีขอบเขตแบบบล็อก (block scope) คือมองเห็นได้ภายใน { } เท่านั้น เหมาะกับการจำกัดขอบเขตให้ชัดเจน ลดการชนกันของตัวแปร.

ตัวอย่าง:

if (true) {
  var a = 1;
  let b = 2;
  const c = 3;
}
console.log(a); // 1
console.log(b); // ReferenceError
console.log(c); // ReferenceError

Hoisting และ Temporal Dead Zone (TDZ)

  • var: ถูก hoist ขึ้นไปบนสุดของ scope และถูกกำหนดค่าเริ่มต้นเป็น undefined ทำให้สามารถอ้างถึงตัวแปรก่อนบรรทัดประกาศได้ (แม้จะได้ค่า undefined) ซึ่งอาจนำไปสู่บั๊กที่ตรวจจับยาก.
  • let / const: ถูก hoist เช่นกัน แต่จะอยู่ใน TDZ จนกว่าจะถึงบรรทัดประกาศ การอ้างถึงก่อนประกาศจะเกิด ReferenceError ช่วยป้องกันการใช้ตัวแปรก่อนพร้อมใช้งาน.

ตัวอย่าง:

console.log(x); // undefined (var)
var x = 10;

console.log(y); // ReferenceError (let ใน TDZ)
let y = 10;

console.log(z); // ReferenceError (const ใน TDZ)
const z = 10;

การประกาศซ้ำและการแก้ค่า

  • var: สามารถประกาศซ้ำชื่อเดิมใน scope เดียวกันได้ และแก้ค่าได้ ทำให้เสี่ยงเขียนทับโดยไม่ตั้งใจ.
  • let: แก้ค่าได้ แต่ “ห้าม” ประกาศซ้ำใน block เดิม ลดความสับสนของชื่อซ้ำ.
  • const: “ห้าม” reassignment หลังตั้งค่าเริ่มต้น และ “ห้าม” ประกาศซ้ำใน block เดิม อย่างไรก็ตาม สำหรับอ็อบเจ็กต์/อาเรย์ที่ประกาศด้วย const คุณยังสามารถ “แก้ไขค่าภายใน” ได้ (mutation) แต่เปลี่ยนตัวแปรให้ชี้ไปยังอ็อบเจ็กต์ใหม่ไม่ได้

ตัวอย่าง:

// var: ประกาศซ้ำได้
var a = 1;
var a = 2; // OK

// let: ห้ามประกาศซ้ำ
let b = 1;
// let b = 2; // SyntaxError

// const: ห้าม reassignment
const c = { name: "Ada" };
c.name = "Grace";   // OK (mutation)
c = { name: "Linus" }; // TypeError (reassignment)

พฤติกรรมในลูปและ closure

  • var ใน for: ใช้ตัวแปรเดียวร่วมกันทุก iteration จนมักทำให้ callback หลังลูปเห็นค่าเดียวกัน (เช่นค่า iteration สุดท้าย).
  • let ใน for: สร้าง binding ใหม่ต่อ iteration จึงทำให้ค่าแต่ละรอบเป็นอิสระ เหมาะกับการใช้ร่วมกับ callback/async ภายในลูป.

ตัวอย่าง:

// var: มักพังใน callback หลังลูป
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log("var i:", i), 0);
}
// Output: var i: 3, var i: 3, var i: 3

// let: ทำงานถูกต้องต่อรอบ
for (let j = 0; j < 3; j++) {
  setTimeout(() => console.log("let j:", j), 0);
}
// Output: let j: 0, let j: 1, let j: 2

แนวทางปฏิบัติที่แนะนำ

  • ใช้ const เป็นค่าเริ่มต้น: หากตัวแปรไม่จำเป็นต้องเปลี่ยน ให้ใช้ const เพื่อสื่อเจตนาและป้องกันการแก้ค่าโดยไม่ตั้งใจ.
  • ใช้ let เมื่อจำเป็นต้องแก้ค่า: เช่น ตัวแปรตัวนับลูป หรือตัวแปรที่ขึ้นกับเงื่อนไขหลายแบบภายในบล็อก.
  • หลีกเลี่ยง var ในโค้ดสมัยใหม่: เพราะ scope กว้างและ hoisting เป็น undefined เพิ่มความเสี่ยงบั๊ก โดยทั่วไป let/const ให้พฤติกรรมคาดเดาง่ายกว่า.

ตารางเปรียบเทียบสรุป

คุณสมบัติvarletconst
ขอบเขตฟังก์ชัน/โกลบอลบล็อกบล็อก
Hoistinghoist เป็น undefinedhoist แต่มี TDZhoist แต่มี TDZ
ประกาศซ้ำได้ไม่ได้ในบล็อกเดียวกันไม่ได้ในบล็อกเดียวกัน
แก้ค่าได้ได้ไม่ได้ (คำาอ้างอิง), แต่ mutate โครงสร้างได้
ใช้ในลูปมีปัญหา closure บ่อยปลอดภัยต่อรอบปลอดภัยต่อรอบ (ถ้าไม่ต้องเปลี่ยนตัวแปร)

สรุป

ใช้ const โดยค่าเริ่มต้น, เปลี่ยนเป็น let เมื่อจำเป็นต้อง reassignment, หลีกเลี่ยง var ในโค้ด ES6+ เพื่อ scope ที่คาดเดาได้และลดบั๊ก.
 JavaScript Tutorial
 2025-12-19 02:17:16
 แชร์หน้านี้:  

ข่าวบันเทิง