การที่คลอเชอร์เก็บสถานะ
ทำความเข้าใจสภาพแวดล้อมเชิงศัพท์ของคลอเชอร์
การที่คลอเชอร์เก็บสถานะ เป็นบทเรียน JavaScript Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน JavaScript Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส JavaScript Academy มีบทเรียนทั้งหมด 4 บทเรียน
คลอเชอร์คืออะไร
คลอเชอร์คือฟังก์ชันที่รวมเข้ากับการอ้างอิงตัวแปรจากขอบเขตที่ฟังก์ชันนั้นถูกกำหนด ฟังก์ชันด้านในจะ “จดจำ” ตัวแปรเหล่านั้นได้ แม้ว่าฟังก์ชันด้านนอกจะคืนค่ากลับไปแล้ว
function outer() {
const message = "hello";
function inner() {
console.log(message); // sees outer variable
}
inner();
}
outer(); // "hello"การคืนค่าฟังก์ชันด้านใน
จุดสำคัญจะเกิดขึ้นเมื่อคุณคืนค่าฟังก์ชันด้านใน ฟังก์ชันนั้นยังเข้าถึงตัวแปรของฟังก์ชันด้านนอกได้ แม้ว่า outer จะทำงานเสร็จไปแล้ว
function outer() {
const message = "remembered";
return function () {
console.log(message);
};
}
const fn = outer();
fn(); // "remembered"ขอบเขตแบบเล็กซิคัล
คลอเชอร์ทำงานได้เนื่องจากการกำหนดขอบเขตแบบเล็กซิคัล ฟังก์ชันสามารถเข้าถึงตัวแปรที่กำหนดอยู่ในขอบเขตซึ่งล้อมรอบฟังก์ชันนั้นตามโครงสร้างในซอร์สโค้ด ไม่ใช่ขอบเขовต์ที่ฟังก์ชันถูกเรียกใช้
const x = 10;
function show() {
console.log(x); // resolves where defined
}
function run() {
const x = 99;
show(); // still logs 10, not 99
}
run();การจับตัวแปรด้วยการอ้างอิง
คลอเชอร์จะจับตัวแปรเอง ไม่ใช่ภาพค่าของตัวแปรในขณะนั้น หากตัวแปรเปลี่ยนแปลงภายหลัง คลอเชอร์ก็จะเห็นค่าใหม่
function make() {
let count = 0;
const get = () => count;
count = 5; // changed after get defined
return get;
}
console.log(make()()); // 5การเรียกใช้แต่ละครั้งสร้างขอบเขตใหม่
การเรียกใช้ฟังก์ชันด้านนอกแต่ละครั้งจะสร้างชุดตัวแปรใหม่ คลอเชอร์จากการเรียกใช้คนละครั้งจะไม่ใช้สถานะร่วมกัน
function counter() {
let n = 0;
return () => ++n;
}
const a = counter();
const b = counter();
console.log(a(), a()); // 1 2
console.log(b()); // 1 (independent)คลอเชอร์กับพารามิเตอร์
พารามิเตอร์ของฟังก์ชันก็ถูกจับไว้เช่นกัน ทำให้คุณสร้างฟังก์ชันเฉพาะทางจากฟังก์ชันทั่วไปได้
function adder(x) {
return (y) => x + y;
}
const add5 = adder(5);
console.log(add5(3)); // 8
console.log(add5(10)); // 15กับดักลูปแบบคลาสสิก
ข้อผิดพลาดที่พบเห็นกันบ่อยคือ การใช้ var ในลูปจะทำให้คลอเชอร์ทั้งหมดใช้ตัวแปรเดียวกัน เมื่อคลอเชอร์เหล่านั้นทำงาน ลูปก็จบไปแล้ว และทุกคลอเชอร์จึงเห็นค่าสุดท้ายเหมือนกัน
const fns = [];
for (var i = 0; i < 3; i++) {
fns.push(() => i);
}
console.log(fns[0](), fns[1](), fns[2]()); // 3 3 3แก้ไขด้วย let
let จะสร้างการผูกค่าใหม่ในการวนซ้ำแต่ละครั้ง ดังนั้นคลอเชอร์แต่ละตัวจึงจับ i ของตัวเองไว้ นี่คือวิธีแก้ไขแบบสมัยใหม่
const fns = [];
for (let i = 0; i < 3; i++) {
fns.push(() => i);
}
console.log(fns[0](), fns[1](), fns[2]()); // 0 1 2คลอเชอร์ทำให้หน่วยความจำยังคงอยู่
ตราบใดที่คลอเชอร์ยังคงอยู่ ตัวแปรที่คลอเชอร์จับไว้จะไม่สามารถถูกเก็บคืนโดยตัวเก็บขยะได้ โดยทั่วไปเรื่องนี้ไม่มีปัญหา แต่ก็อาจทำให้หน่วยความจำรั่วไหลได้ หากคุณเก็บคลอเชอร์ไว้นานเกินความจำเป็น
function make() {
const big = new Array(3).fill("data");
return () => big.length;
}
const f = make();
console.log(f()); // 3 - big stays in memory via fคลอเชอร์อยู่ทุกที่
ฟังก์ชันเรียกกลับ ตัวจัดการเหตุการณ์ setTimeout เมธอดของอาร์เรย์ และพรอมิส ล้วนพึ่งพาคลอเชอร์เพื่อจดจำบริบท คุณใช้งานสิ่งเหล่านี้อยู่เสมอโดยมักไม่ทันสังเกต
function greet(name) {
return () => console.log("Hi " + name);
}
[greet("Ada"), greet("Bob")].forEach((fn) => fn());
// Hi Ada
// Hi Bobตรวจสอบสถานะที่ถูกจับไว้
คลอเชอร์หลายตัวจากการเรียกใช้ครั้งเดียวกันจะแชร์ตัวแปรที่ถูกจับไว้ชุดเดียวกัน ดังนั้นคลอเชอร์หนึ่งจึงอ่านค่าที่อีกคลอเชอร์หนึ่งเขียนได้
function pair() {
let value = 0;
return {
set: (v) => { value = v; },
get: () => value
};
}
const p = pair();
p.set(42);
console.log(p.get()); // 42ตรวจสอบความเข้าใจอย่างรวดเร็ว
วิธีที่คลอเชอร์จับสถานะไว้
ทบทวน
คลอเชอร์คือฟังก์ชันที่มาพร้อมการอ้างอิงไปยังขอบเขตที่ใช้กำหนดฟังก์ชันนั้น ด้วยขอบเขตแบบเล็กซิคัล คลอเชอร์จึงจดจำตัวแปรภายนอกได้แม้ฟังก์ชันภายนอกจะทำงานเสร็จแล้ว โดยจับตัวแปรเหล่านั้นตามการอ้างอิง ไม่ใช่ตามค่า การเรียกใช้ฟังก์ชันภายนอกแต่ละครั้งจะสร้างขอบเขตที่เป็นอิสระต่อกัน และควรใช้ let เพื่อหลีกเลี่ยงกับดักของลูป คลอเชอร์ทำให้หน่วยความจำที่ถูกจับไว้ยังคงอยู่ และเป็นพลังเบื้องหลังฟังก์ชันเรียกกลับทั่วทั้งระบบ
คำถามที่พบบ่อย
บทเรียน “การที่คลอเชอร์เก็บสถานะ” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การที่คลอเชอร์เก็บสถานะ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส JavaScript Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส JavaScript Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การที่คลอเชอร์เก็บสถานะ”
ทำความเข้าใจสภาพแวดล้อมเชิงศัพท์ของคลอเชอร์ คุณปฏิบัติ JavaScript Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน JavaScript Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน JavaScript Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “การที่คลอเชอร์เก็บสถานะ” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน JavaScript Academy นี้ได้ไหม
ได้ บทเรียน JavaScript Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การที่คลอเชอร์เก็บสถานะ
- ตัวแปรส่วนตัวด้วยคลอเชอร์
- รูปแบบโมดูล (IIFE)
- ฟังก์ชันโรงงาน