นิยามฟังก์ชั่นการโทรกลับ
ฟังก์ชั่นการเรียกกลับเป็นฟังก์ชั่นที่เรียกผ่านตัวชี้ฟังก์ชั่น หากคุณผ่านตัวชี้ (ที่อยู่) ของฟังก์ชั่นเป็นอาร์กิวเมนต์ไปยังฟังก์ชั่นอื่นเมื่อตัวชี้นี้ใช้เรียกฟังก์ชันที่ชี้ไปที่เราบอกว่านี่เป็นฟังก์ชันการโทรกลับ ฟังก์ชั่นการโทรกลับไม่ได้ถูกเรียกโดยตรงโดยผู้ดำเนินการของฟังก์ชั่น แต่ถูกเรียกโดยบุคคลอื่นเมื่อมีเหตุการณ์หรือเงื่อนไขเฉพาะเกิดขึ้นและใช้เพื่อตอบสนองต่อเหตุการณ์หรือเงื่อนไข
ใน JavaScript คำจำกัดความเฉพาะของฟังก์ชั่นการโทรกลับคือ: ฟังก์ชั่น A ถูกส่งผ่านเป็นพารามิเตอร์ (การอ้างอิงฟังก์ชั่น) ลงในฟังก์ชันอื่น B และฟังก์ชัน B นี้เรียกใช้ฟังก์ชัน A. สมมติว่าฟังก์ชัน A เรียกว่าฟังก์ชันการโทรกลับ หากไม่มีชื่อ (นิพจน์ฟังก์ชั่น) จะเรียกว่าฟังก์ชันการโทรกลับที่ไม่ระบุชื่อ ดังนั้นการโทรกลับจึงไม่จำเป็นต้องใช้สำหรับความไม่เปลี่ยนแปลง การเรียกกลับมักจะใช้ในสถานการณ์จำลองแบบซิงโครนัส (การบล็อก) ทั่วไปเช่นต้องการให้มีการดำเนินการบางอย่างและฟังก์ชั่นการเรียกกลับ
ตัวอย่าง
ตัวอย่างของการใช้การเรียกกลับในการซิงโครไนซ์ (การบล็อก) คือการเรียกใช้ FunC2 หลังจากเรียกใช้รหัส FUNC1
การคัดลอกรหัสมีดังนี้:
var func1 = ฟังก์ชั่น (โทรกลับ) {
// ทำอะไรบางอย่าง
(การโทรกลับ && typeof (การโทรกลับ) === "ฟังก์ชั่น") && callback ();
-
func1 (func2);
var func2 = function () {
-
ใช้กรณีของฟังก์ชั่นการโทรกลับ
การโหลดทรัพยากร: เรียกใช้การโทรกลับหลังจากการโหลดแบบไดนามิกของไฟล์ JS, เรียกใช้การโทรกลับหลังจากโหลด iframe, เรียกใช้การโทรกลับหลังจากโหลดการดำเนินการโทรกลับ AJAX, เรียกใช้การเรียกกลับหลังจากการโหลดอิมเมจ, AJAX ฯลฯ
เหตุการณ์ DOM และเหตุการณ์ Node.js ขึ้นอยู่กับกลไกการโทรกลับ (node.js callbacks อาจมีปัญหาการทำรังกลับหลายชั้น)
เวลาหน่วงของการตั้งถิ่นฐานคือ 0 แฮ็คนี้มักจะใช้ ฟังก์ชั่นที่เรียกโดย settimeout เป็นศูนย์รวมการโทรกลับ
สายโซ่: เมื่อสายโซ่เป็นเรื่องง่ายที่จะใช้การโทรแบบโซ่ในเมธอดผู้ประเมิน (setter) (หรือในวิธีการที่ไม่คืนค่า) แต่ค่า getter นั้นค่อนข้างยากที่จะใช้สายโซ่เนื่องจากคุณต้องการค่า getter เพื่อส่งคืนข้อมูลที่คุณต้องการแทนตัวชี้นี้ หากคุณต้องการใช้เมธอดโซ่คุณสามารถใช้ฟังก์ชั่นการโทรกลับเพื่อใช้งานได้
การเรียกใช้ฟังก์ชันของ settimeout และ setInterval จะได้รับค่าส่งคืน เนื่องจากฟังก์ชั่นทั้งสองเป็นแบบอะซิงโครนัสนั่นคือเวลาการโทรและกระบวนการหลักของโปรแกรมค่อนข้างเป็นอิสระจึงไม่มีวิธีที่จะรอมูลค่าการคืนค่าของพวกเขาในร่างกายและโปรแกรมจะไม่หยุดและรอเมื่อเปิดออก ดังนั้นจึงไม่มีความหมายที่จะใช้การส่งคืนดังนั้นจึงสามารถใช้การโทรกลับได้เท่านั้น ความหมายของการโทรกลับคือการแจ้งฟังก์ชั่นพร็อกซีของผลการดำเนินการจับเวลาสำหรับการประมวลผลที่เหมาะสม
ฟังก์ชั่นเป็นวัตถุ
หากคุณต้องการเข้าใจฟังก์ชั่นการโทรกลับคุณต้องเข้าใจกฎของฟังก์ชั่นอย่างชัดเจนก่อน ในจาวาสคริปต์ฟังก์ชั่นแปลก แต่ก็เป็นวัตถุ เพื่อความแม่นยำฟังก์ชั่นเป็นวัตถุฟังก์ชั่นที่สร้างขึ้นด้วยตัวสร้างฟังก์ชัน () วัตถุฟังก์ชันมีสตริงที่มีรหัส JavaScript ของฟังก์ชัน หากคุณถูกถ่ายโอนจาก C หรือ Java นี่อาจดูแปลก ๆ รหัสจะเป็นสตริงได้อย่างไร? แต่สำหรับ JavaScript นี่เป็นเรื่องธรรมดา ความแตกต่างระหว่างข้อมูลและรหัสนั้นคลุมเครือ
การคัดลอกรหัสมีดังนี้:
// ฟังก์ชั่นสามารถสร้างได้ด้วยวิธีนี้
var fn = ฟังก์ชันใหม่ ("arg1", "arg2", "return arg1 * arg2;");
FN (2, 3); // 6
ข้อดีอย่างหนึ่งของสิ่งนี้คือคุณสามารถส่งรหัสไปยังฟังก์ชั่นอื่น ๆ หรือคุณสามารถผ่านตัวแปรหรือวัตถุปกติ (เพราะรหัสเป็นเพียงวัตถุเพียงวัตถุ)
ฟังก์ชั่นการถ่ายโอนเป็นการโทรกลับ
มันง่ายที่จะผ่านฟังก์ชั่นเป็นพารามิเตอร์
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่น fn (arg1, arg2, callback) {
var num = math.ceil (math.random () * (arg1 - arg2) + arg2);
การโทรกลับ (num); // ส่งผล
-
FN (10, 20, ฟังก์ชั่น (NUM) {
console.log ("โทรกลับเรียก! num:" + num);
}); // ผลลัพธ์คือหมายเลขสุ่มระหว่าง 10 ถึง 20
บางทีการทำเช่นนี้ดูเหมือนจะยุ่งยากและโง่ไปหน่อยทำไมไม่กลับผลลัพธ์ที่ผิดปกติ? แต่เมื่อคุณต้องใช้ฟังก์ชั่นการโทรกลับคุณอาจไม่คิดอย่างนั้น!
อย่าไปขวางทาง
ฟังก์ชั่นดั้งเดิมป้อนข้อมูลเป็นพารามิเตอร์และใช้คำสั่งส่งคืนเพื่อส่งคืนค่า ในทางทฤษฎีมีคำสั่ง return return ที่ส่วนท้ายของฟังก์ชันซึ่งมีโครงสร้าง: จุดอินพุตและจุดเอาต์พุต เข้าใจง่ายกว่า ฟังก์ชั่นกำลังแมปกระบวนการใช้งานระหว่างอินพุตและเอาต์พุตเป็นหลัก
อย่างไรก็ตามเมื่อกระบวนการใช้งานของฟังก์ชั่นยาวมากคุณควรเลือกที่จะรอให้ฟังก์ชั่นเสร็จสิ้นการประมวลผลหรือใช้ฟังก์ชั่นการโทรกลับเพื่อทำการประมวลผลแบบอะซิงโครนัส? ในกรณีนี้การใช้ฟังก์ชั่นการโทรกลับกลายเป็นสิ่งสำคัญเช่น: คำขอ AJAX หากคุณใช้ฟังก์ชั่นการโทรกลับสำหรับการประมวลผลรหัสสามารถดำเนินการต่อไปเพื่อทำงานอื่น ๆ โดยไม่ต้องล้าง ในการพัฒนาจริงการโทรแบบอะซิงโครนัสมักใช้ใน JavaScript และขอแนะนำอย่างยิ่งที่นี่!
ด้านล่างเป็นตัวอย่างที่ครอบคลุมมากขึ้นในการโหลดไฟล์ XML โดยใช้ AJAX และใช้ฟังก์ชันการโทร () เพื่อเรียกใช้ฟังก์ชันการเรียกกลับในบริบทของวัตถุที่ร้องขอ
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่น fn (url, callback) {
var httprequest; // สร้าง XHR
httprequest = window.xmlhttprequest? ใหม่ XMLHTTPREQUEST ():
window.activexobject? ใหม่ ActiveXObject ("microsoft.xmlhttp"): undefined; // การตรวจจับการทำงานสำหรับ IE
httpRequest.onreadyStateChange = function () {
if (httprequest.readystate === 4
&& httprequest.status === 200) {// การตัดสินสถานะ
callback.call (httprequest.responsexml);
-
-
httprequest.open ("รับ", url);
httprequest.send ();
-
fn ("text.xml", function () {// การเรียกใช้ฟังก์ชัน
console.log (นี่); // เอาต์พุตหลังจากคำสั่งนี้
-
console.log ("สิ่งนี้จะทำงานก่อนการโทรกลับข้างต้น"); // คำสั่งนี้เป็นเอาต์พุตก่อน
คำขอของเราสำหรับการประมวลผลแบบอะซิงโครนัสหมายความว่าเมื่อเราเริ่มร้องขอเราบอกให้พวกเขาเรียกฟังก์ชั่นของเราเมื่อเสร็จสิ้น ในสถานการณ์จริงตัวจัดการเหตุการณ์ onreadystatechange จะต้องพิจารณาความล้มเหลวของคำขอ ที่นี่เราสมมติว่ามีไฟล์ XML อยู่และสามารถโหลดได้สำเร็จโดยเบราว์เซอร์ ในตัวอย่างนี้ฟังก์ชั่นอะซิงโครนัสถูกกำหนดให้กับเหตุการณ์ OnReadyStateChange และดังนั้นจะไม่ถูกดำเนินการทันที
ในที่สุดคำสั่ง console.log ที่สองจะถูกดำเนินการก่อนเนื่องจากฟังก์ชั่นการโทรกลับจะไม่ถูกดำเนินการจนกว่าคำขอจะเสร็จสมบูรณ์
ตัวอย่างข้างต้นไม่ใช่เรื่องง่ายที่จะเข้าใจดังนั้นลองดูตัวอย่างต่อไปนี้:
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่น foo () {
var a = 10;
return function () {
a *= 2;
กลับ A;
-
-
var f = foo ();
f (); // return 20
f (); // return 40
ฟังก์ชั่นนี้เรียกว่าภายนอกและยังสามารถเข้าถึงตัวแปร ทั้งหมดนี้เป็นเพราะขอบเขตในจาวาสคริปต์เป็นคำศัพท์ การทำงานทำงานในขอบเขตที่กำหนด (ขอบเขตภายใน Foo ในตัวอย่างด้านบน) แทนที่จะอยู่ในขอบเขตที่ฟังก์ชั่นนี้ทำงาน ตราบใดที่ F ถูกกำหนดไว้ใน FOO ก็สามารถเข้าถึงตัวแปรทั้งหมดที่กำหนดไว้ใน FOO แม้ว่าการดำเนินการของ FOO ได้สิ้นสุดลง เนื่องจากขอบเขตของมันจะถูกบันทึก แต่เฉพาะฟังก์ชั่นที่ส่งคืนสามารถเข้าถึงขอบเขตที่บันทึกไว้ การกลับฟังก์ชั่นที่ไม่ระบุชื่อแบบฝังเป็นวิธีที่พบบ่อยที่สุดในการสร้างการปิด