var, let, const และขอบเขต Scopeตัวแปร (Variable) คือชื่อที่ใช้เก็บค่าเพื่อนำไปใช้งานภายหลัง ส่วน Scope คือขอบเขตที่ตัวแปรสามารถถูกเข้าถึงได้
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#458588", "primaryTextColor": "#fbf1c7", "primaryBorderColor": "#fabd2f", "lineColor": "#a89984", "secondaryColor": "#b8bb26", "tertiaryColor": "#d3869b", "background": "#282828", "mainBkg": "#3c3836", "textColor": "#ebdbb2"}}}%%
flowchart TD
A["Variable Declaration
การประกาศตัวแปร"] --> B["var
Function Scope"]
A --> C["let
Block Scope"]
A --> D["const
Block Scope + assign once"]
B --> E["Hoisting
ถูกยกประกาศขึ้น"]
C --> F["TDZ
Temporal Dead Zone"]
D --> F
var, let, const| คำสั่ง | Scope | Hoisting | เปลี่ยนค่าได้ | ประกาศซ้ำใน scope เดิม |
|---|---|---|---|---|
var |
Function Scope | มี | ได้ | ได้ |
let |
Block Scope | มีแต่ติด TDZ | ได้ | ไม่ได้ |
const |
Block Scope | มีแต่ติด TDZ | ไม่ได้เมื่อเป็น binding | ไม่ได้ |
var: Function Scope และปัญหาที่ควรหลีกเลี่ยงvar มีขอบเขตระดับฟังก์ชัน ไม่ใช่ระดับ block และถูก hoist ทำให้อ่านโค้ดยากในหลายกรณี
function demoVar() {
// var ถูก hoist ทำให้เข้าถึงก่อนประกาศได้ แต่ค่าเป็น undefined
console.log(score); // undefined
if (true) {
var score = 80;
}
// var ไม่ถูกจำกัดใน if block
console.log(score); // 80
}
// ตัวอย่างการใช้งาน
demoVar();
let: Block Scope สำหรับค่าที่เปลี่ยนได้let เหมาะกับตัวแปรที่ต้องเปลี่ยนค่า และมีขอบเขตตาม block เช่น { ... }
function demoLet() {
let total = 0;
for (let i = 1; i <= 3; i++) {
// i อยู่ใน scope ของ for block
total += i;
}
console.log(total); // 6
}
// ตัวอย่างการใช้งาน
demoLet();
const: Block Scope สำหรับค่าคงที่const ต้อง assign ค่าทันที และไม่สามารถเปลี่ยน binding ไปชี้ค่าใหม่ได้
const passingScore = 50;
const student = { name: "Ana", score: 82 };
// Object ที่ประกาศด้วย const ยังแก้ property ได้
student.score = 90;
console.log(passingScore); // 50
console.log(student); // { name: "Ana", score: 90 }
{ ... }const appName = "Grade App"; // Global Scope
function calculate() {
const score = 75; // Function Scope
if (score >= 50) {
const result = "ผ่าน"; // Block Scope
console.log(result);
}
}
calculate();
console.log(appName);
TDZ คือช่วงตั้งแต่เริ่ม block จนถึงบรรทัดที่ประกาศ let หรือ const ซึ่งตัวแปรยังถูกเข้าถึงไม่ได้
function demoTDZ() {
// console.log(name); // ReferenceError
const name = "Web Programming";
console.log(name);
}
demoTDZ();
Closure คือฟังก์ชันที่จดจำ scope ของตัวเองได้ แม้ถูกเรียกใช้นอก scope เดิม
function createCounter() {
let count = 0;
return function increase() {
// increase จำตัวแปร count ได้
count += 1;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
โดยที่ countₙ คือค่าหลังเรียกฟังก์ชัน n ครั้ง, count₀ คือค่าเริ่มต้น, และ n คือจำนวนครั้งที่เรียกฟังก์ชัน
var ในโค้ดสมัยใหม่let และ const มี scope แบบใดconst ยังแก้ property ได้