หลายคนสับสนระหว่าง Undeclared (ไม่ได้ประกาศ) และ Undefined (ประกาศแต่ไม่มีค่า) ทั้งคู่เกี่ยวกับตัวแปรที่ "ไม่มีค่า" แต่ความหมายและพฤติกรรมต่างกันหมด
ความแตกต่างพื้นฐาน
| ลักษณะ | Undeclared (ไม่ได้ประกาศ) | Undefined (ไม่มีค่า) |
|---|---|---|
| สาเหตุ | ไม่เคยใช้ var, let, const ประกาศ | ประกาศแล้วแต่ไม่ได้กำหนดค่า |
| การเข้าถึง | ❌ โยน ReferenceError | ✅ คืนค่า undefined |
| typeof | "undefined" (ไม่โยน Error) | "undefined" |
| Scope | กลายเป็น Global Property (ใน Non-strict) | อยู่ใน Scope ที่ประกาศ |
| Strict Mode | ❌ ReferenceError เสมอ | ✅ ปกติ |
ตัวอย่างแสดงความแตกต่าง
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Undeclared vs Undefined</title>
<style>
body { font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; padding: 20px; }
.result { font-size: 18px; font-weight: 500; color: blueviolet; margin: 10px 0; padding: 10px; background: #f8f9fa; }
button { padding: 8px 16px; margin: 10px 0; cursor: pointer; }
.error { color: #dc3545; }
</style>
</head>
<body>
<h1>Undeclared vs Undefined ใน JavaScript</h1>
<div class="result" id="undefinedResult"></div>
<div class="result" id="undeclaredResult"></div>
<button class="Btn" id="testBtn">ทดสอบการเข้าถึงตัวแปร</button>
<h3>กดปุ่มเพื่อเข้าถึงตัวแปร Undefined และ Undeclared</h3>
<script>
const undefinedResult = document.getElementById("undefinedResult");
const undeclaredResult = document.getElementById("undeclaredResult");
const btn = document.getElementById("testBtn");
// Declared but not assigned = undefined
let a;
btn.addEventListener("click", () => {
// 1. เข้าถึงตัวแปร undefined
undefinedResult.innerHTML = `เข้าถึงตัวแปร undefined (let a;) = ${a}
`;
undefinedResult.innerHTML += `typeof a = "${typeof a}"`;
// 2. เข้าถึงตัวแปร undeclared (b ไม่ได้ประกาศ)
try {
undeclaredResult.innerHTML = `เข้าถึงตัวแปร undeclared (b) = ${b}`;
} catch (err) {
undeclaredResult.innerHTML = `เข้าถึงตัวแปร undeclared = ${err.name}: ${err.message}
`;
undeclaredResult.innerHTML += `typeof b = "${typeof b}" (typeof ไม่โยน Error)`;
}
});
</script>
</body>
</html>
ผลลัพธ์
Undefined (let a;):
เข้าถึง = undefined
typeof a = "undefined"
Undeclared (b ไม่ได้ประกาศ):
เข้าถึง = ReferenceError: b is not defined
typeof b = "undefined" (typeof ไม่โยน Error!)
รายละเอียดเพิ่มเติม
1. Undefined - ค่าที่ "ไม่มีค่า" อย่างเป็นทางการ
let x; // undefined
let y = undefined; // undefined (Explicit)
let z = void 0; // undefined (Alternative)
function foo() {} // return undefined
foo(); // undefined
const obj = {};
obj.missingProp; // undefined (Property ไม่มีอยู่)
2. Undeclared - ตัวแปรที่ "ไม่มีอยู่จริง"
// Non-strict mode (Legacy)
function test() {
undeclaredVar = 10; // สร้าง Global Variable! (Implicit Global)
}
test();
console.log(window.undeclaredVar); // 10
// Strict Mode ("use strict")
function testStrict() {
"use strict";
undeclaredVar = 10; // ❌ ReferenceError: undeclaredVar is not defined
}
3. ตรวจสอบอย่างปลอดภัย
// ✅ ปลอดภัย - ใช้ typeof (ไม่โยน Error ทั้งคู่)
if (typeof myVar === "undefined") {
console.log("myVar เป็น undeclared หรือ undefined");
}
// ✅ ปลอดภัย - ใช้ try/catch
try {
myVar; // ReferenceError ถ้า undeclared
} catch (e) {
console.log("undeclared");
}
// ✅ สำหรับ Object Properties - ใช้ in operator / hasOwnProperty
if ("prop" in obj) { } // true ถ้ามีใน Prototype Chain
if (obj.hasOwnProperty("prop")) { } // true ถ้าเป็น Own Property
Best Practices
- ✅ ใช้
let/constเสมอ (Block Scope, TDZ ป้องกัน Undeclared Access) - ✅ ใช้
"use strict"หรือ ES Modules (Strict Mode โดยอัตโนมัติ) - ✅ เริ่มต้นค่าให้ตัวแปรเสมอ:
let x = null;หรือlet x = 0; - ✅ ตรวจสอบด้วย
typeof x === "undefined"สำหรับ Global Check - ❌ หลีกเลี่ยง Implicit Globals (Assignment โดยไม่มี Declaration)