โคลเชอร์ (Closure) ในภาษา JavaScript

โคลเชอร์ (Closure) ในภาษา JavaScript

บทความนี้อธิบายเกี่ยวกับโคลเชอร์ (Closure) ในภาษา JavaScript

YouTube Video

โคลเชอร์ (Closure) ในภาษา JavaScript

ในภาษา JavaScript 'โคลเชอร์' เป็นหนึ่งในแนวคิดที่สำคัญและทรงพลังมาก ด้วยการเข้าใจโคลเชอร์ คุณจะได้รับความรู้ที่มีประโยชน์ในหลาย ๆ สถานการณ์ เช่น พฤติกรรมและขอบเขตการทำงานของฟังก์ชัน รวมถึงการประมวลผลแบบอะซิงโครนัสและการจัดการอีเวนต์ใน JavaScript ที่นี่เราจะอธิบายทุกอย่างอย่างละเอียด ตั้งแต่นิยามพื้นฐานของโคลเชอร์ ไปจนถึงตัวอย่างการใช้งานจริง

โคลเชอร์ คืออะไร?

โคลเชอร์ หมายถึงกลไกที่ฟังก์ชันสามารถเข้าถึงตัวแปรในขอบเขตที่ถูกประกาศ แม้จะเรียกใช้งานฟังก์ชันนั้นจากภายนอกขอบเขตดังกล่าว ด้วยการใช้โคลเชอร์ ฟังก์ชันสามารถ 'จดจำ' ตัวแปรภายนอกของตัวเองได้อย่างต่อเนื่อง

โคลเชอร์ ประกอบด้วยสององค์ประกอบหลักดังต่อไปนี้

  1. นิยามฟังก์ชัน (ตัวฟังก์ชันเอง)

  2. ขอบเขตที่นิยามฟังก์ชัน (ตัวแปรและฟังก์ชันอื่นๆ ที่อยู่นอกตัวฟังก์ชัน)

ในภาษา JavaScript โคลเชอร์ เป็นไปได้เพราะฟังก์ชันสามารถเข้าถึงตัวแปรในขอบเขตที่ฟังก์ชันถูกสร้างขึ้นมาได้

ตัวอย่างพื้นฐาน

ก่อนอื่น มาดูตัวอย่างพื้นฐานของโคลเชอร์ กัน ในโค้ดต่อไปนี้ outerFunction จะให้ค่ากลับเป็นฟังก์ชันที่ชื่อว่า innerFunction จุดที่สำคัญคือ innerFunction สามารถเข้าถึงตัวแปร count ที่ถูกประกาศในขอบเขตของ outerFunction ได้

 1function outerFunction() {
 2    let count = 0;
 3
 4    function innerFunction() {
 5        count++;
 6        console.log(`Current count: ${count}`);
 7    }
 8
 9    return innerFunction;
10}
11
12const counter = outerFunction();
13counter(); // Current count: 1
14counter(); // Current count: 2
15counter(); // Current count: 3

วิธีการทำงานของโคลเชอร์

อย่างที่เห็นในตัวอย่างด้านบน ตัวแปร count จะยังคงอยู่ให้ innerFunction ใช้งานได้แม้ว่า outerFunction จะถูกเรียกและจบการทำงานไปแล้ว innerFunction ยังคงสามารถเข้าถึงขอบเขตของ outerFunction ได้ และทำให้ count ถูกปรับค่าภายใน innerFunction นี่คือกลไกพื้นฐานของโคลเชอร์

ฟังก์ชัน innerFunction ถูกกำหนดให้กับตัวแปร counter และเราสังเกตได้ว่าสถานะของ count ยังคงอยู่แม้ว่า outerFunction จะทำงานจบไปแล้ว เป็นเพราะ JavaScript 'จดจำ' ขอบเขตขณะที่ฟังก์ชันถูกสร้างขึ้นมาไว้นั่นเอง

การประยุกต์ใช้งาน: ใช้โคลเชอร์ เป็นตัวแปรส่วนตัว (Private Variable)

โคลเชอร์ สามารถนำมาใช้เป็น 'ตัวแปรส่วนตัว' แบบเดียวกับการเขียนโปรแกรมเชิงวัตถุ โดยปกติใน JavaScript สมาชิกของอ็อบเจกต์สามารถเข้าถึงได้โดยตรงจากภายนอก แต่ด้วยการใช้โคลเชอร์ เราสามารถป้องกันไม่ให้เข้าถึงหรือล้วงลึกตัวแปรภายในขอบเขตของฟังก์ชันจากภายนอกได้

ในตัวอย่างถัดไป ฟังก์ชัน createCounter ใช้โคลเชอร์ เพื่อสร้างตัวนับ (Counter) และส่งกลับตัวนับที่มีตัวแปรส่วนตัวชื่อ count

 1function createCounter() {
 2    let count = 0;
 3
 4    return {
 5        increment: function() {
 6            count++;
 7            console.log(`Count: ${count}`);
 8        },
 9        decrement: function() {
10            count--;
11            console.log(`Count: ${count}`);
12        },
13        getCount: function() {
14            return count;
15        }
16    };
17}
18
19const myCounter = createCounter();
20myCounter.increment(); // Count: 1
21myCounter.increment(); // Count: 2
22myCounter.decrement(); // Count: 1
23console.log(myCounter.getCount()); // 1

ในตัวอย่างนี้ count อยู่ในขอบเขตของฟังก์ชัน createCounter จึงไม่สามารถเข้าถึงโดยตรงจากภายนอกได้ แต่สามารถปรับค่าโดยใช้เมธอด increment และ decrement ได้ ดังนั้นการใช้โคลเชอร์ ก็ช่วยให้สามารถประยุกต์แนวคิดของตัวแปรส่วนตัวเข้ามาใช้ใน JavaScript ได้

ตัวอย่างการใช้โคลเชอร์ ในทางปฏิบัติ

การใช้ร่วมกับฟังก์ชัน Callback

โคลเชอร์ มักถูกใช้ร่วมกับฟังก์ชัน Callback เพื่อจัดการกับกระบวนการแบบอะซิงโครนัส ตัวอย่างเช่น มาดูตัวอย่างที่ใช้ตัวจับเวลา (Timer)

 1function startTimer(duration) {
 2    let timeLeft = duration;
 3
 4    function countdown() {
 5        console.log(`Time left: ${timeLeft} seconds`);
 6        timeLeft--;
 7
 8        if (timeLeft >= 0) {
 9            setTimeout(countdown, 1000);
10        }
11    }
12
13    countdown();
14}
15
16startTimer(5);
17// Time left: 5 seconds
18// Time left: 4 seconds
19// Time left: 3 seconds
20// Time left: 2 seconds
21// Time left: 1 second
22// Time left: 0 seconds

ในตัวอย่างนี้ ฟังก์ชัน countdown จะเข้าถึงตัวแปร timeLeft ที่อยู่ในขอบเขตของ startTimer ด้วยวิธีนี้ โคลเชอร์ มีประโยชน์มากสำหรับการทำงานแบบอะซิงโครนัส เช่น ตัวจับเวลา เพราะสามารถเก็บสถานะของตัวแปรไว้ได้ตลอดเวลา

Event Handler (ตัวจัดการเหตุการณ์)

โคลเชอร์ ก็สะดวกต่อการตั้งค่า Event Handler เช่นกัน ในตัวอย่างต่อไปนี้ โคลเชอร์ ถูกใช้เพื่อบันทึกจำนวนครั้งที่ปุ่มถูกคลิก

 1function setupClickCounter(buttonId) {
 2    let clickCount = 0;
 3
 4    const button = document.getElementById(buttonId);
 5    button.addEventListener('click', function() {
 6        clickCount++;
 7        console.log(`Button clicked ${clickCount} times`);
 8    });
 9}
10
11setupClickCounter('myButton');

กรณีนี้ค่า clickCount จะเพิ่มขึ้นทุกครั้งที่คลิก และค่าจะถูกเก็บเอาไว้ ด้วยการใช้โคลเชอร์ คุณสามารถกำหนดตัวนับแยกสำหรับแต่ละปุ่มได้

สรุป

โคลเชอร์ เป็นแนวคิดที่แสดงถึงความยืดหยุ่นและพลังของ JavaScript โคลเชอร์ เก็บรักษาตัวแปรที่ถูกห่อหุ้มในขอบเขตฟังก์ชันไว้ และอนุญาตให้เข้าถึงหรือจัดการตัวแปรนั้นผ่านฟังก์ชันที่เข้าถึงได้จากภายนอก ด้วยความเข้าใจและการใช้กลไกนี้ คุณจะสามารถพัฒนาทักษะในการเขียนโค้ด JavaScript ได้อย่างก้าวหน้า

โคลเชอร์ ถูกนำไปใช้ในสถานการณ์ต่าง ๆ เช่น การจัดการเหตุการณ์ การประมวลผลแบบอะซิงโครนัส หรือแม้แต่การสร้างการจำลองแบบเชิงวัตถุ (OOP) ใน JavaScript

คุณสามารถติดตามบทความข้างต้นโดยใช้ Visual Studio Code บนช่อง YouTube ของเรา กรุณาตรวจสอบช่อง YouTube ด้วย

YouTube Video