1. ขอบเขตของตัวแปร
เพื่อให้เข้าใจการปิดคุณต้องเข้าใจขอบเขตตัวแปรพิเศษของ JavaScript ก่อน
มีเพียงสองประเภทของตัวแปร: ตัวแปรทั่วโลกและตัวแปรท้องถิ่น
คุณสมบัติพิเศษของภาษา JavaScript คือตัวแปรทั่วโลกสามารถอ่านได้โดยตรงภายในฟังก์ชั่น
var n = 999; ฟังก์ชั่น f1 () {แจ้งเตือน (n); } f1 (); // 999ในทางกลับกันตัวแปรท้องถิ่นภายในฟังก์ชั่นจะไม่อ่านนอกฟังก์ชั่นตามธรรมชาติ
ฟังก์ชั่น f1 () {var n = 999; } Alert (n); // ข้อผิดพลาดมีสถานที่ที่ควรทราบที่นี่ เมื่อประกาศตัวแปรภายในคุณต้องใช้คำสั่ง VAR ถ้าไม่คุณก็ประกาศตัวแปรทั่วโลก!
ฟังก์ชั่น f1 () {n = 999; } f1 (); การแจ้งเตือน (n); // 9992. จะอ่านตัวแปรท้องถิ่นจากภายนอกได้อย่างไร?
ด้วยเหตุผลต่าง ๆ บางครั้งเราจำเป็นต้องได้รับตัวแปรท้องถิ่นภายในฟังก์ชั่น อย่างไรก็ตามดังที่ได้กล่าวไว้ก่อนหน้านี้ภายใต้สถานการณ์ปกติสิ่งนี้ไม่สามารถทำได้และสามารถทำได้ผ่านการแก้ปัญหาเท่านั้น
นั่นคือการกำหนดฟังก์ชั่นอื่นภายในฟังก์ชั่น
ฟังก์ชั่น f1 () {var n = 999; ฟังก์ชั่น f2 () {แจ้งเตือน (n); // 999}}ในรหัสด้านบนฟังก์ชั่น F2 รวมอยู่ในฟังก์ชั่น F1 และตัวแปรท้องถิ่นทั้งหมดภายใน F1 สามารถมองเห็นได้ที่ F2 แต่วิธีอื่น ๆ ก็เป็นไปไม่ได้ ตัวแปรท้องถิ่นภายใน F2 นั้นมองไม่เห็นที่ F1 นี่คือโครงสร้าง "ขอบเขตโซ่" ที่ไม่ซ้ำกับภาษาจาวาสคริปต์ วัตถุลูกจะมองขึ้นไปตามระดับตามระดับสำหรับตัวแปรวัตถุแม่ทั้งหมด ดังนั้นตัวแปรทั้งหมดของวัตถุหลักจะมองเห็นได้จากวัตถุลูกไม่เช่นนั้นจะไม่เป็นความจริง
เนื่องจาก F2 สามารถอ่านตัวแปรท้องถิ่นใน F1 ได้ตราบใดที่ F2 ใช้เป็นค่าส่งคืนเราไม่สามารถอ่านตัวแปรภายในนอก F1 ได้หรือไม่?
ฟังก์ชั่น f1 () {var n = 999; ฟังก์ชั่น f2 () {แจ้งเตือน (n); } return f2; } var result = f1 (); ผลลัพธ์(); // 9993. แนวคิดของการปิด
ฟังก์ชั่น F2 ในส่วนก่อนหน้าของรหัสคือการปิด
คำจำกัดความของ "การปิด" ในเอกสารมืออาชีพต่าง ๆ เป็นนามธรรมและเข้าใจยากมาก ความเข้าใจของฉันคือการปิดเป็นฟังก์ชั่นที่สามารถอ่านตัวแปรภายในฟังก์ชั่นอื่น ๆ
เนื่องจากในภาษา JavaScript เฉพาะฟังก์ชั่นย่อยภายในฟังก์ชั่นเท่านั้นที่สามารถอ่านตัวแปรท้องถิ่นการปิดสามารถเข้าใจได้ง่ายว่าเป็น "ฟังก์ชั่นที่กำหนดไว้ในฟังก์ชั่น"
ดังนั้นในสาระสำคัญการปิดคือสะพานเชื่อมต่อด้านในและด้านนอกของฟังก์ชั่น
4. จุดประสงค์ในการปิด
การปิดสามารถใช้ในหลายสถานที่ มันมีการใช้งานที่ใหญ่ที่สุดสองครั้งหนึ่งคือตัวแปรภายในฟังก์ชั่นสามารถอ่านได้ตามที่กล่าวไว้ข้างต้นและอื่น ๆ คือค่าของตัวแปรเหล่านี้จะถูกเก็บไว้ในหน่วยความจำเสมอ
จะเข้าใจประโยคนี้ได้อย่างไร? โปรดดูรหัสด้านล่าง
ฟังก์ชั่น f1 () {var n = 999; nadd = function () {n+= 1} ฟังก์ชั่น f2 () {การแจ้งเตือน (n); } return f2; } var result = f1 (); ผลลัพธ์(); // 999 NADD (); ผลลัพธ์(); // 1,000ในรหัสนี้ผลลัพธ์คือฟังก์ชั่นปิด F2 มันทำงานทั้งหมดสองครั้งค่าแรกคือ 999 และค่าที่สองคือ 1,000 นี่พิสูจน์ได้ว่าตัวแปรท้องถิ่นในฟังก์ชั่น F1 ถูกเก็บไว้ในหน่วยความจำและไม่ได้รับการล้างโดยอัตโนมัติหลังจากเรียก F1 โดยอัตโนมัติ
ทำไมสิ่งนี้ถึงเกิดขึ้น? เหตุผลก็คือ F1 เป็นฟังก์ชั่นหลักของ F2 และ F2 ถูกกำหนดให้กับตัวแปรทั่วโลกซึ่งทำให้ F2 อยู่ในหน่วยความจำเสมอและการมีอยู่ของ F2 ขึ้นอยู่กับ F1 ดังนั้น F1 จึงอยู่ในหน่วยความจำเสมอและจะไม่ถูกรีไซเคิลโดยกลไกการรวบรวมขยะหลังจากการโทรเสร็จสิ้น
อีกจุดสำคัญในรหัสนี้คือบรรทัด "nadd = function () {n+= 1}" ถูกใช้ก่อน NADD ดังนั้น NADD จึงเป็นตัวแปรส่วนกลางไม่ใช่ตัวแปรท้องถิ่น ประการที่สองค่าของ NADD เป็นฟังก์ชั่นที่ไม่ระบุชื่อและฟังก์ชั่นนิรนามนี้เองก็เป็นการปิดดังนั้น NADD จึงเทียบเท่ากับ setter ซึ่งสามารถทำงานกับตัวแปรท้องถิ่นภายในฟังก์ชั่นนอกฟังก์ชั่น
5. หมายเหตุเกี่ยวกับการใช้การปิด
1) เนื่องจากการปิดจะทำให้ตัวแปรทั้งหมดในฟังก์ชันถูกเก็บไว้ในหน่วยความจำและการใช้หน่วยความจำมีขนาดใหญ่มากการปิดไม่สามารถถูกทารุณกรรมไม่เช่นนั้นจะทำให้เกิดปัญหาประสิทธิภาพของหน้าเว็บและอาจนำไปสู่การรั่วไหลของหน่วยความจำใน IE วิธีแก้ปัญหาคือการลบตัวแปรท้องถิ่นทั้งหมดที่ไม่ได้ใช้ก่อนออกจากฟังก์ชั่น
2) การปิดจะเปลี่ยนค่าของตัวแปรภายในฟังก์ชั่นหลักนอกฟังก์ชั่นหลัก ดังนั้นหากคุณใช้ฟังก์ชั่นหลักเป็นวัตถุให้ใช้การปิดเป็นวิธีการสาธารณะและใช้ตัวแปรภายในเป็นคุณสมบัติส่วนตัวโปรดระวังอย่าเปลี่ยนค่าของตัวแปรภายในของฟังก์ชันหลักที่จะ