สมัครเรียนโทร. 085-350-7540 , 084-88-00-255 , ntprintf@gmail.com


JavaScript05_Closure

ในบทความนี้จะพูดถึงเรื่องฟังก์ชัน Closure ในภาษา JavaScript แต่ก่อนอื่นจะขอทบทวนเรื่องตัวแปร (Variable) เสียก่อน สำหรับผู้อ่านที่เข้าใจเรื่องตัวแปรอยู่แล้วก็ข้ามไปอ่านข้างล่างได้เลยครับ

JavaScript Variables

ตัวแปรในภาษา JavaScript สามารถแบ่งได้เป็น ตัวแปร local และตัวแปร global ซึ่งมีลักษณะดังนี้

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

ตัวอย่าง a เป็น ตัวแปร local:

function myFunction() {
    var a = 1;
    return a + a;
}

2. ตัวแปร global เป็นตัวแปรที่สามารถเรียกใช้ได้จากทุกที่ และใช้งานได้ตลอดเวลาจนกว่าจะปิด Application (เช่น หน้าเว็บ)
ตัวอย่าง a เป็น ตัวแปร global:

var a = 1;
function myFunction() {
    return a + a;
}

ข้อควรระวังเกี่ยวกับตัวแปรใน JavaScript

  • ตัวแปร local และตัวแปร global ที่มีชื่อเดียวกันจะถือเป็นคนละตัว ดังนั้นการเปลี่ยนค่าของตัวแปรหนึ่งจะไม่ส่งผลต่ออีกตัวแปรหนึ่ง
  • ตัวแปรที่สร้างโดยไม่ใช้คีย์เวิร์ด var จะกลายเป็นตัวแปร global เสมอ แม้ว่าจะสร้างตัวแปรนั้นในฟังก์ชันก็ตาม

ปัญหาการสร้างฟังก์ชันนับเลข

หากเราต้องการสร้างฟังก์ชันสำหรับนับตัวเลขให้เพิ่มขึ้นเรื่อยๆทุกครั้งที่มีการเรียกฟังก์ชันนี้ เราจะทำอย่างไรดี??? มาลองดูตัวอย่างการสร้างฟังก์ชันแล้วเรียกใช้งานฟังก์ชันนี้ 3 ครั้งกัน

วิธีที่ 1 สร้างฟังก์ชันแบบปกติ แล้วให้มาใช้ตัวแปร global

var counter = 0;
function count() {
    counter += 1;
}

count();
count();
count();

วิธีนี้ผลลัพธ์ที่ได้จะได้ค่า counter เป็น 3 ซึ่งแน่นอนว่าถ้าเอาไปใช้งานก็ถือว่าเป็นโค้ดที่ทำงานได้ถูกต้อง แต่ปัญหาของวิธีนี้คือไม่ว่าใครก็สามารถมาเรียกใช้งานตัวแปร counter นี้ได้โดยตรง ซึ่งในทางการเขียนโปรแกรมแล้วนับว่าเป็นการเขียนโปรแกรมที่ไม่ดีเอาเสียเลย วิธีเขียนโปรแกรมที่ดีคือตัวแปร counter ควรจะเป็นตัวแปร local ที่เรียกผ่านได้ทางฟังก์ชัน count() เท่านั้น เพื่อป้องกันไม่ให้คนอื่นมาเปลี่ยนค่าตัวแปรนี้ได้

วิธีที่ 2 สร้าง counter เป็นตัวแปร local ด้วย

var counter = 0;
function count() {
    var counter = 0; 
    counter += 1;
}

count();
count();
count();

วิธีนี้มองผ่านๆ ผู้อ่านอาจจะคิดว่าหลังจากเรียกฟังก์ชัน count() ครบ 3 ครั้งแล้วจะได้ค่า counter เป็น 3 แต่ใน JavaScript นั้น ตัวแปร local และตัวแปร global ที่มีชื่อเดียวกันจะถือเป็นคนละตัว การเปลี่ยนค่าของตัวแปร counter ในฟังก์ชันจะไม่ส่งผลต่ออีกตัวแปร counter ที่อยู่นอกฟังก์ชัน ดังนั้นค่า counter ที่ได้ก็คือ 0 เหมือนเดิม เมื่อเป็นเช่นนั้นเราก็มาลองเอาตัวแปร global ทิ้ง แล้วเรียกฟังก์ชันจากภายในดู

วิธีที่ 3 สร้างฟังก์ชันซ้อนไว้ข้างใน

function count() {
    var counter = 0;
    function plus() {
        counter += 1;
    }
    plus();    
    return counter; 
}

count();
count();
count();

วิธีนี้ดูเหมือนจะใช้ได้ เพราะฟังก์ชัน plus() สามารถเข้าถึงตัวแปร couter ได้ แต่เราจะเรียกฟังก์ชัน plus() จากภายนอกได้อย่างไร?

หมายเหตุ: สำหรับคนที่งงว่าทำไมฟังก์ชัน plus() ถึงใช้งานตัวแปร counter ได้ ตรงจุดนี้ต้องทำความเข้าใจเรื่อง scope ก่อนครับ ในตอนที่ผมอธิบายเรื่องตัวแปร global ไปว่าเป็นตัวแปรที่เข้าถึงได้จากทุกที่ (global scopt) นั้น จริงๆแล้วถ้าพูดให้ละเอียดก็คือฟังก์ชันทุกฟังก์ชันสามารถเข้าถึงตัวแปรที่อยู่ scope เหนือมันได้ ซึ่งจะพบได้บ่อยตอนเขียนฟังก์ชันซ้อนฟังก์ชันอย่างในวิธีที่ 3 นี้ที่ฟังก์ชัน plus() สามารถเข้าถึงตัวแปร counter ที่เป็นตัวแปรของฟังก์ชันแม่จึงอยู่ scope เหนือมันได้ (parent scope) 

ผู้อ่านคงจะเริ่มเกิดคำถามว่าวิธีที่ 1 ก็ไม่ดี วิธีที่ 2 ก็ใช้ไม่ได้ วิธีที่ 3 ก็ไม่รู้จะเรียกฟังก์ชันที่อยู่ข้างในฟังก์ชันอย่างไร แล้วจะให้ทำอย่างไร? ไม่ต้องกังวลไปครับ ปัญหานี้ JavaScript มีวิธีแก้ไขให้เราเรียบร้อยแล้ว นั่นก็คือ การใช้สิ่งที่เรียกว่า Closure นั่นเอง

Closure คืออะไร?

Closure คือ ฟังก์ชันที่สามารถเข้าถึงตัวแปรใน parent scope ได้ แม้ว่าฟังก์ชันแม่นั้นจะจบไปแล้วก็ตาม ลองมาดูตัวอย่างฟังก์ชันนับเลขในวิธีที่ 4 กัน

วิธีที่ 4 สร้างฟังก์ชัน Closure 

function count() {
    var counter = 0;
    return function() {
        counter += 1;
        return counter; 
    }
}

var plus = count();
plus();
plus();
plus();

ในวิธีที่ 4 เราสร้างตัวแปร plus ขึ้่นมาแล้วกำหนดให้รับค่าที่คืนกลับมาจากฟังก์ชัน count() ซึ่งสิ่งที่คืนกลับมาก็คือฟังก์ชัน ทำให้ตัวแปร plus กลายเป็นฟังก์ชันนั่นเอง จากตัวอย่างนี้ จะเห็นได้ว่า Closure ทำให้ฟังก์ชันสามารถมีตัวแปร private ได้ และตัวแปรนี้จะไม่สามารถเรียกจากภายนอกฟังก์ชันได้โดยตรง ต้องเรียกผ่านฟังก์ชัน plus() เท่านั้น 

เย้! สำเร็จแล้วครับ เท่านี้ก็เราก็สร้างฟังก์ชันนับเลขอย่างที่ต้องการได้แล้ว ต่อไปเรามาลองแสดงผล Hello World ออกทางหน้าจอด้วย Closure กัน

Project Hello world ด้วย Closure

คราวนี้เราจะมาลองเขียนฟังก์ชันชื่อ show ซ้อนไว้ในฟังก์ชัน message เพื่อให้แสดงข้อความด้วย Closure กันครับ

1. เริ่มจากสร้างไฟล์ที่เราจะใช้เขียนโค้ดขึ้นมาก่อน โดยการคลิกขวาในโฟลเดอร์ที่เราต้องการแล้วเลือก New > Text Document เหมือนบทความก่อนหน้านี้ จากนั้นเปลี่ยนชื่อและนามสกุลไฟล์ ในที่นี้ตั้งชื่อว่า javascript04.html

2. เปิดไฟล์ด้วยโปรแกรมทีี่สามารถแก้ไขข้อความในไฟล์ได้ เช่น Notepad หรือ Notepad++ จากนั้นพิมพ์โค้ดต่อไปนี้ลงไป แล้วกด Save

อธิบายโค้ดส่วน JavaScript:
บรรทัดที่ 4 - 10 เป็นการสร้างฟังก์ชัน Closure
บรรทัดที่ 12 เป็นการสร้างตัวแปรชื่อ myFunction ให้รับค่าจากฟังก์ชัน message

3. ดับเบิ้ลคลิกที่ไฟล์ javascript04.html ที่เราเขียนโค้ดไว้แล้วในขั้นตอนที่ 2 จะเห็นหน้าต่างเว็บปรากฏขึ้นมา ให้ทดลองกดปุ่ม Click me จะเห็นว่ามีข้อความ Hello World ปรากฏขึ้นมา

เท่านี้เราก็จะสามารถเขียนโค้ด JavaScript เพื่อแสดงข้อความ Hello World ด้วย Closure ได้แล้ว ไม่งงใช่ไหมครับ? ถ้าอยากรู้เรื่องของ Closure เพิ่มเติมก็อ่านได้จาก [1] และ [2] นะครับ 

สุดท้ายนี้ถ้าผู้อ่านอยากเรียนรู้เรื่อง JavaScript และเรื่องเกี่ยวกับ Web Programming อย่างลึกซึ้งก็ขอแนะนำคอร์ส Web Programming ของทาง EPT ครับ สามารถดูรายละเอียดคอร์สได้โดยคลิกที่นี่หรือติดต่อได้ที่ 085-350-7540

แล้วพบกันใหม่บทความหน้านะครับ

 

ที่มาและเว็บไซต์อ้างอิง

[1] https://www.w3schools.com/js/js_function_closures.asp
[2] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures


Tag ที่น่าสนใจ: java c# vb.net python c c++ machine_learning web database oop cloud aws ios android


บทความนี้อาจจะมีที่ผิด กรุณาตรวจสอบก่อนใช้

หากมีข้อผิดพลาด/ต้องการพูดคุยเพิ่มเติมเกี่ยวกับบทความนี้ กรุณาแจ้งที่ http://m.me/Expert.Programming.Tutor

ไม่อยากอ่าน Tutorial อยากมาเรียนเลยทำอย่างไร?

สมัครเรียน ONLINE ได้ทันทีที่ https://elearn.expert-programming-tutor.com

หรือติดต่อ

085-350-7540 (DTAC)
084-88-00-255 (AIS)
026-111-618
หรือทาง EMAIL: NTPRINTF@GMAIL.COM

แผนที่ ที่ตั้งของอาคารของเรา

แผนผังการเรียนเขียนโปรแกรม

Link อื่นๆ

Allow sites to save and read cookie data.
Cookies are small pieces of data created by sites you visit. They make your online experience easier by saving browsing information. We use cookies to improve your experience on our website. By browsing this website, you agree to our use of cookies.

Copyright (c) 2013 expert-programming-tutor.com. All rights reserved. | 085-350-7540 | 084-88-00-255 | ntprintf@gmail.com

ติดต่อเราได้ที่

085-350-7540 (DTAC)
084-88-00-255 (AIS)
026-111-618
หรือทาง EMAIL: NTPRINTF@GMAIL.COM
แผนที่ ที่ตั้งของอาคารของเรา