บทบาทของรูปแบบการออกแบบ JavaScript คือการปรับปรุงความสามารถในการใช้ซ้ำและการอ่านของรหัสทำให้รหัสง่ายต่อการบำรุงรักษาและขยาย
ใน JavaScript ฟังก์ชั่นเป็นคลาสของวัตถุซึ่งหมายความว่าสามารถส่งผ่านเป็นพารามิเตอร์ไปยังฟังก์ชั่นอื่น ๆ นอกจากนี้ฟังก์ชั่นยังสามารถให้ขอบเขต
ไวยากรณ์สำหรับการสร้างฟังก์ชัน
ชื่อการแสดงออกของฟังก์ชั่น
// ชื่อฟังก์ชั่นนิพจน์ var เพิ่ม = ฟังก์ชั่นเพิ่ม (a, b) {return a+b;}; var foo = function bar () {console.log (foo === bar);}; foo (); // trueจะเห็นได้ว่าพวกเขาอ้างถึงฟังก์ชั่นเดียวกัน แต่นี่เป็นเพียงการใช้งานในร่างกายฟังก์ชั่น
var foo = bar function () {}; console.log (foo === bar); // ReferenceRror: BAR ไม่ได้กำหนดไว้อย่างไรก็ตามคุณไม่สามารถโทรหาฟังก์ชั่นได้โดยเรียกแถบ ()
var foo = (function bar () {console.log (foo === bar);}) (); // falseการแสดงออกของฟังก์ชั่น
// หรือที่รู้จักกันในชื่อฟังก์ชันที่ไม่ระบุชื่อ var add = function (a, b) {return a+b;};ค่าที่กำหนดให้กับการเพิ่มตัวแปรคือนิยามฟังก์ชันเอง ด้วยวิธีนี้เพิ่มกลายเป็นฟังก์ชั่นที่สามารถเรียกได้ทุกที่
การประกาศฟังก์ชั่น
function foo () {// code ที่นี่} // ไม่จำเป็นต้องมีเครื่องหมายอัฒภาคที่นี่ในเครื่องหมายอัฒภาคที่ตามมาการแสดงออกของฟังก์ชั่นควรใช้เครื่องหมายอัฒภาคเสมอและการสิ้นสุดของเครื่องหมายอัฒภาคไม่จำเป็นต้องใช้ในการประกาศของฟังก์ชั่น
ความแตกต่างระหว่างฟังก์ชั่นการประกาศและการแสดงออกของฟังก์ชั่นคือในช่วงระยะเวลาการควบคุมล่วงหน้าของ JS ฟังก์ชั่นการประกาศจะถูกแยกออกก่อนจากนั้นรหัส JS จะถูกดำเนินการตามลำดับ:
console.log (f1); // [ฟังก์ชั่น: f1]
console.log (f2); // undefined, JavaScript ไม่ได้ตีความและดำเนินการอย่างสมบูรณ์ตามลำดับ แต่จะ "precompile" JavaScript ก่อนการตีความ ในระหว่างกระบวนการ precompilation ฟังก์ชั่นที่ชัดเจนจะถูกดำเนินการก่อน
ฟังก์ชั่น f1 () {console.log ("I am f1");} var f2 = function () {console.log ("I am f2");};เนื่องจากฟังก์ชั่นการประกาศจะแล้วเสร็จในระหว่างการก่อสร้างขอบเขตทั่วโลกการประกาศฟังก์ชั่นเป็นคุณสมบัติของวัตถุหน้าต่างซึ่งแสดงให้เห็นว่าทำไมไม่ว่าเราจะประกาศฟังก์ชั่นที่ไหนประกาศฟังก์ชั่นในที่สุดก็เป็นของวัตถุหน้าต่าง
ในภาษาจาวาสคริปต์ฟังก์ชั่นใด ๆ ที่ไม่ระบุชื่อเป็นของวัตถุหน้าต่าง เมื่อกำหนดฟังก์ชั่นที่ไม่ระบุชื่อมันจะส่งคืนที่อยู่หน่วยความจำ หากตัวแปรได้รับที่อยู่หน่วยความจำนี้ในเวลานี้ฟังก์ชันที่ไม่ระบุชื่อสามารถใช้ในโปรแกรมได้เนื่องจากฟังก์ชั่นที่ไม่ระบุชื่อถูกกำหนดและกำหนดในระหว่างการก่อสร้างสภาพแวดล้อมการดำเนินการทั่วโลกดังนั้นการชี้ของฟังก์ชันที่ไม่ระบุชื่อจึงเป็นวัตถุหน้าต่าง
var f2 = function () {console.log ("ฉันเป็น f2");}; console.log (f2 ()); // ฉันเป็น f2 (ฟังก์ชัน () {console.log (this === หน้าต่าง); // true}) ();การประกาศฟังก์ชั่นและการแสดงออก
โปรโมชั่นฟังก์ชั่น (Hoisting)
พฤติกรรมของการประกาศฟังก์ชั่นไม่เทียบเท่ากับการแสดงออกของฟังก์ชันที่มีชื่อ ความแตกต่างคือพฤติกรรมการยก ดูตัวอย่างต่อไปนี้:
<script type = "text/javascript"> // ฟังก์ชั่นฟังก์ชั่นทั่วโลก foo () {แจ้งเตือน ("global foo!");} function bar () {Alert (' global bar');} function hoist () {console.log (typeof foo); bar (); // typeError: 'undefined' ไม่ใช่ฟังก์ชั่น // ตัวแปร foo และตัวติดตั้งได้รับการส่งเสริมฟังก์ชั่น foo () {alert ('local foo! '); } // เฉพาะแถบตัวแปรเท่านั้นที่ได้รับการส่งเสริมส่วนการใช้งานฟังก์ชันไม่ได้รับการส่งเสริม var bar = function () {การแจ้งเตือน ('local bar!'); - } hoist (); </script>สำหรับตัวแปรทั้งหมดไม่ว่าจะมีการประกาศในร่างกายที่ไหนพวกเขาจะได้รับการเลื่อนตำแหน่งภายในให้กับด้านบนของฟังก์ชั่น เหตุผลสำหรับการใช้งานทั่วไปของฟังก์ชั่นคือฟังก์ชั่นเป็นเพียงวัตถุที่กำหนดให้กับตัวแปรเท่านั้น
ตามชื่อแนะนำการปรับปรุงหมายถึงการกล่าวถึงสิ่งต่อไปนี้ไปด้านบน ใน JS มันคือการอัพเกรดสิ่งที่กำหนดไว้ใน (ตัวแปรหรือฟังก์ชั่น) ต่อไปนี้เป็นคำจำกัดความก่อนหน้า ดังที่เห็นได้จากตัวอย่างข้างต้น Foo และ Bar ในฟังก์ชั่นยกขึ้นภายในฟังก์ชั่นเคลื่อนที่ไปด้านบนซึ่งครอบคลุมฟังก์ชั่น Foo และ Bar ทั่วโลก ความแตกต่างระหว่างแถบฟังก์ชั่นท้องถิ่นและ Foo คือ Foo ได้รับการเลื่อนตำแหน่งให้อยู่ด้านบนและสามารถทำงานได้ตามปกติในขณะที่คำจำกัดความของ Bar () ยังไม่ได้รับการปรับปรุง ดังนั้นเมื่อมีการดำเนินการ bar () ผลลัพธ์จะไม่ได้กำหนดแทนที่จะใช้เป็นฟังก์ชัน
โหมดฟังก์ชันเรียลไทม์
ฟังก์ชั่นเป็นวัตถุดังนั้นจึงสามารถใช้เป็นค่าส่งคืน ข้อได้เปรียบของการใช้ฟังก์ชั่นการดำเนินการด้วยตนเองคือการประกาศฟังก์ชั่นที่ไม่ระบุชื่อโดยตรงและใช้งานทันทีเพื่อหลีกเลี่ยงการกำหนดฟังก์ชั่นที่ไม่ได้ใช้ครั้งเดียวและหลีกเลี่ยงจากปัญหาการตั้งชื่อความขัดแย้ง ไม่มีแนวคิดของเนมสเปซใน JS ดังนั้นจึงเป็นเรื่องง่ายที่จะมีชื่อฟังก์ชั่นความขัดแย้ง เมื่อเกิดความขัดแย้งการตั้งชื่อแล้วคนสุดท้ายก็ประกาศว่าจะได้รับชัยชนะ
โหมด 1:
<script> (function () {var a = 1; return function () {Alert (2);};} () ()); // 2 ปรากฏขึ้นวงเล็บแรกจะดำเนินการเองรูปแบบที่ 2: การชี้ของตัวแปรฟังก์ชันที่กำลังดำเนินการด้วยตนเอง
<script type = "text/javascript"> var result = (function () {return 2;}) (); // การแจ้งเตือนของฟังก์ชัน (ผลลัพธ์); // คะแนนผลลัพธ์ไปยังค่าส่งคืน 2 ของฟังก์ชั่นที่ดำเนินการด้วยตนเอง; หากผลลัพธ์ () ปรากฏขึ้นข้อผิดพลาดจะเกิดขึ้น </script>รูปแบบที่สาม: ฟังก์ชั่นซ้อนกัน
<script type = "text/javascript"> var result = (function () {return function () {return 2;};}) (); การแจ้งเตือน (result ()); // เมื่อแจ้งเตือน (ผลลัพธ์) ฟังก์ชัน () {return 2} </script>โหมด 4: ฟังก์ชั่น Execution Self-Execution กำหนดค่าการส่งคืนให้กับตัวแปร
var abc = (function () {var a = 1; return function () {return ++ a;}}) (); // ฟังก์ชั่นของฟังก์ชั่นที่กำลังดำเนินการด้วยตนเองส่งคืนฟังก์ชั่นหลังจากกลับไปที่การแจ้งเตือนตัวแปร (abc ()); // หากเป็นการแจ้งเตือน (ABC) หากเป็น ABC () ฟังก์ชั่นหลังการส่งคืนจะถูกดำเนินการรูปแบบที่ 5: ฟังก์ชั่นดำเนินการตัวเองภายใน
// นี่คือฟังก์ชั่นที่ดำเนินการด้วยตนเองฟังก์ชั่นดำเนินการภายในฟังก์ชั่นการเรียกซ้ำ ABC () {ABC (); -โหมดโทรกลับ
ฟังก์ชั่นการโทรกลับ: เมื่อคุณผ่านฟังก์ชั่นเขียน () เป็นอาร์กิวเมนต์ไปยังการเรียกใช้ฟังก์ชันอื่น () จากนั้น call () อาจเรียกใช้ (หรือการโทร) เขียน () ในบางจุด ในกรณีนี้เขียน () เรียกว่าฟังก์ชันการโทรกลับ
ผู้ฟังเหตุการณ์แบบอะซิงโครนัส
โหมดการโทรกลับมีการใช้งานจำนวนมากตัวอย่างเช่นเมื่อผู้ฟังเหตุการณ์ถูกแนบกับองค์ประกอบในหน้าจริงมันจะให้ตัวชี้ไปยังฟังก์ชั่นการโทรกลับที่จะถูกเรียกเมื่อเหตุการณ์เกิดขึ้น ชอบ:
document.addeventListener ("คลิก", console.log, false);
ตัวอย่างโค้ดด้านบนแสดงฟังก์ชั่นการโทรกลับ console.log () ในโหมดฟองเมื่อเอกสารคลิก
JavaScript เหมาะอย่างยิ่งสำหรับการเขียนโปรแกรมที่ขับเคลื่อนด้วยเหตุการณ์เนื่องจากโหมดการโทรกลับรองรับโปรแกรมเพื่อเรียกใช้แบบอะซิงโครนัส
หมดเวลา
อีกตัวอย่างหนึ่งของการใช้โหมดการโทรกลับคือเมื่อใช้วิธีการหมดเวลาที่จัดทำโดยวัตถุหน้าต่างของเบราว์เซอร์: settimeout () และ setInterval () เช่น:
<script type = "text/javascript"> var call = function () {console.log ("100ms จะถูกถาม ... "); - settimeout (โทร, 100); </script>โหมดโทรกลับในไลบรารี
เมื่อออกแบบไลบรารี JS ฟังก์ชั่นการโทรกลับจะมีประโยชน์ รหัสของไลบรารีควรใช้รหัสที่นำกลับมาใช้ใหม่ได้มากที่สุดและการโทรกลับสามารถช่วยให้บรรลุพื้นฐานนี้ได้ เมื่อเราออกแบบห้องสมุด JS ขนาดใหญ่ความจริงก็คือผู้ใช้ไม่ต้องการส่วนใหญ่เราสามารถมุ่งเน้นไปที่ฟังก์ชั่นหลักและให้ฟังก์ชั่นการโทรกลับใน "ฟอร์มเบ็ด" ซึ่งจะทำให้เราสามารถสร้างปรับขนาดและปรับแต่งวิธีไลบรารีได้ง่ายขึ้น
การแกงกะหรี่
Currying เป็นเทคนิคที่แปลงฟังก์ชั่นเป็นฟังก์ชั่นใหม่ (เพื่อยอมรับพารามิเตอร์ที่น้อยลง) ใหม่โดยการกรอกพารามิเตอร์หลายตัวลงในร่างกายฟังก์ชั่น ―
พูดง่ายๆคือ Curryization เป็นกระบวนการแปลงนั่นคือกระบวนการของการแปลงฟังก์ชั่นของเรา ดังที่แสดงในตัวอย่างต่อไปนี้:
<script type = "text/javascript"> // ฟังก์ชั่น Add Function ที่ใช้แกงกะหรี่ () เพิ่ม (x, y) {var oldx = x, oldy = y; if (typeof oldy == "undefined") {return function (newy) {return oldx + newy; - } // ใช้ return x+y อย่างสมบูรณ์; } // test typeof add (5); // output "function" เพิ่ม (3) (4); // 7 // สร้างและจัดเก็บฟังก์ชั่นใหม่ var add2000 = เพิ่ม (2000); add2000 (10); // output 2010 </script>เมื่อเพิ่ม () ถูกเรียกเป็นครั้งแรกมันจะสร้างการปิดสำหรับฟังก์ชั่นภายในที่ส่งคืน การปิดนี้เก็บค่า X และ Y ดั้งเดิมไว้ในตัวแปรส่วนตัว oldx และ oldy
ตอนนี้เราจะสามารถใช้ฟังก์ชั่นโดยพลการแกงวิธีทั่วไปเช่น:
<script type = "text/javascript"> // ฟังก์ชั่นฟังก์ชั่นสามัญเพิ่ม (x, y) {return x + y; } // Curry A ฟังก์ชั่นเพื่อรับฟังก์ชั่นใหม่ var newadd = ทดสอบ (เพิ่ม, 5); newAdd (4); // 9 // ตัวเลือกอื่นเรียกใช้การทดสอบฟังก์ชั่นใหม่โดยตรง (เพิ่ม, 6) (7); // output 13 </script>เมื่อใดควรใช้แกงกะหรี่
เมื่อพบว่ามีการเรียกฟังก์ชั่นเดียวกันและพารามิเตอร์ที่ผ่านส่วนใหญ่จะเหมือนกันฟังก์ชั่นอาจเป็นตัวเลือกที่ดีสำหรับ curryization