เชี่ยวชาญวิธีที่ closure จับตัวแปรเอาไว้ เพื่อให้คุณห่อหุ้มสถานะและหลีกเลี่ยงกับดักเรื่องขอบเขตได้
เปิดบทเรียนนี้ใน Kodokonclosure ไม่ใช่ลูกเล่นแปลกประหลาดอะไร มันคือกลไกที่ทำให้ฟังก์ชันยังคงเข้าถึงขอบเขตแบบเล็กซิคัลที่มันถูก นิยาม ไว้ได้ ไม่ใช่ที่ที่มันถูกเรียกใช้ เอนจินไม่ได้คัดลอกค่า แต่เก็บ การอ้างอิงที่มีชีวิต ไปยังสภาพแวดล้อมเล็กซิคัล ดังนั้นการเรียกโรงงาน (factory) เดียวกันสองครั้งจึงสร้างสภาพแวดล้อมที่แยกจากกันสองชุด ซึ่งทำให้ closure เป็นเครื่องมือห่อหุ้มที่เบาที่สุดในภาษานี้
function createCounter() {
let count = 0;
return {
increment: () => ++count,
reset: () => { count = 0; },
};
}
const counterA = createCounter();
const counterB = createCounter();
counterA.increment();
counterA.increment();
console.log(counterA.increment()); // 3
console.log(counterB.increment()); // 1กับดักคลาสสิกในโลกจริง: var ผูกอยู่กับฟังก์ชันที่ครอบมันไว้ ไม่ใช่กับบล็อก ภายในลูป closure ทุกตัวจึงจับตัวแปร ตัวเดียวกัน ไว้ ด้วย let การวนแต่ละรอบจะสร้างสภาพแวดล้อมเล็กซิคัลใหม่ ดังนั้นการจับแต่ละครั้งจึงแยกจากกัน เพิ่มเข้าไปด้วย temporal dead zone (TDZ): ตัวแปร let หรือ const มีอยู่ทันทีที่เข้าสู่บล็อก แต่จะโยน ReferenceError หากคุณอ่านมันก่อนการประกาศ
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0); // 3, 3, 3
}
for (let j = 0; j < 3; j++) {
setTimeout(() => console.log(j), 0); // 0, 1, 2
}ในแง่ของแพทเทิร์น closure คือรากฐานของ memoization และ module pattern เมื่อเทียบกับคลาส closure ให้ความเป็นส่วนตัวอย่างแท้จริงโดยไม่ต้องมี this หรือโปรโตไทป์ แต่แลกมาด้วยการใช้หน่วยความจำที่สูงขึ้นเล็กน้อยเมื่อคุณสร้างอินสแตนซ์นับพัน: แต่ละอินสแตนซ์พกฟังก์ชันของตัวเองมาด้วย
function memoize(fn) {
const cache = new Map();
return function (key) {
if (cache.has(key)) return cache.get(key);
const result = fn(key);
cache.set(key, result);
return result;
};
}
const square = (n) => n * n;
const fastSquare = memoize(square);
console.log(fastSquare(9)); // computed
console.log(fastSquare(9)); // read from the cachefor (var i = ...) คอลแบ็ก setTimeout สามตัวที่สร้างภายในตัวลูปจะแสดงผลอะไร?createCounter ถึงรับประกันว่า count ยังคงเป็นส่วนตัว?