คำอธิบายโดยละเอียดเกี่ยวกับการสร้างแลนดิ้งเพจ Adobe Muse แลนดิ้งเพจคืออะไร? ปัจจัยสามประการมีความสำคัญสำหรับพวกเขา
แนวคิดที่สำคัญอีกประการหนึ่งในการเขียนโค้ดคือ ฟังก์ชั่น ซึ่งช่วยให้คุณสามารถจัดเก็บโค้ดที่ทำงานชิ้นเดียวภายในบล็อกที่กำหนด จากนั้นจึงเรียกโค้ดนั้นทุกครั้งที่คุณต้องการโดยใช้คำสั่งสั้นๆ คำสั่งเดียว แทนที่จะต้องพิมพ์คำสั่งเดียวกัน รหัสหลายครั้ง ในบทความนี้ เราจะสำรวจแนวคิดพื้นฐานเบื้องหลังฟังก์ชันต่างๆ เช่น ไวยากรณ์พื้นฐาน วิธีเรียกใช้และกำหนดฟังก์ชัน ขอบเขต และพารามิเตอร์
ความรู้คอมพิวเตอร์ขั้นพื้นฐาน ความเข้าใจพื้นฐานเกี่ยวกับ HTML และ CSS ขั้นตอนแรก JavaScript |
เพื่อทำความเข้าใจแนวคิดพื้นฐานเบื้องหลังฟังก์ชัน JavaScript |
ใน JavaScript คุณจะพบฟังก์ชันต่างๆ ทุกที่ จริงๆ แล้ว เราใช้ฟังก์ชันต่างๆ ตลอดหลักสูตรจนถึงตอนนี้ เราแค่ไม่ได้พูดถึงพวกมันมากนัก อย่างไรก็ตาม ตอนนี้ถึงเวลาแล้วที่เราจะเริ่มต้นพูดถึงฟังก์ชันต่างๆ อย่างชัดเจน และสำรวจไวยากรณ์ของพวกมันอย่างแท้จริง
แทบทุกเวลาที่คุณใช้โครงสร้าง JavaScript ที่มีวงเล็บคู่ - () - และคุณไม่ได้ใช้โครงสร้างภาษาในตัวทั่วไป เช่น for loop ในขณะที่ หรือ do... While loop หรือ if ..else คำสั่ง คุณกำลังใช้ฟังก์ชัน
ฟังก์ชั่นเบราว์เซอร์ในตัวหลักสูตรนี้เราได้ใช้ฟังก์ชันที่มีอยู่ในเบราว์เซอร์เป็นจำนวนมาก ทุกครั้งที่เราจัดการสตริงข้อความ เช่น:
Var myText = "ฉันเป็นสตริง"; var newString = myText.replace("string", "ไส้กรอก"); console.log(สตริงใหม่); // ฟังก์ชันสตริงแทนที่() รับสตริง // แทนที่สตริงย่อยหนึ่งด้วยอีกสตริงหนึ่ง และส่งคืน // สตริงใหม่ที่มีการแทนที่
หรือทุกครั้งที่เราจัดการอาร์เรย์:
Var myArray = ["ฉัน", "ความรัก", "ช็อคโกแลต", "กบ"]; var madeAString = myArray.join(" "); console.log(ทำAString); // ฟังก์ชัน join() รับอาร์เรย์ รวม // รายการอาร์เรย์ทั้งหมดเข้าด้วยกันเป็นสตริงเดียว // และส่งกลับสตริงใหม่นี้
หรือทุกครั้งที่เราสร้างตัวเลขสุ่ม:
วาร์ myNumber = Math.random(); // ฟังก์ชัน Random() สร้างตัวเลขสุ่ม // ระหว่าง 0 ถึง 1 และส่งคืน // หมายเลขนั้น
เรากำลังใช้ฟังก์ชัน!
หมายเหตุ: คุณสามารถป้อนบรรทัดเหล่านี้ลงในคอนโซล JavaScript ของเบราว์เซอร์ของคุณเพื่อทำความคุ้นเคยกับฟังก์ชันการทำงานอีกครั้ง หากจำเป็น
ภาษา JavaScript มีฟังก์ชันในตัวมากมายที่ช่วยให้คุณทำสิ่งที่มีประโยชน์ได้โดยไม่ต้องเขียนโค้ดทั้งหมดด้วยตัวเอง ในความเป็นจริง โค้ดบางส่วนที่คุณกำลังเรียกใช้เมื่อคุณเรียกใช้ (คำแฟนซีสำหรับเรียกใช้หรือเรียกใช้งาน) ฟังก์ชันเบราว์เซอร์ในตัวไม่สามารถเขียนเป็น JavaScript ได้ - ฟังก์ชันเหล่านี้จำนวนมากกำลังเรียกส่วนต่างๆ ของโค้ดเบราว์เซอร์พื้นหลัง ซึ่ง ส่วนใหญ่เขียนด้วยภาษาระบบระดับต่ำเช่น C++ ไม่ใช่ภาษาเว็บเช่น JavaScript
โปรดจำไว้ว่าฟังก์ชันเบราว์เซอร์ในตัวบางอย่าง ไม่ได้ส่วนหนึ่งของภาษาหลัก JavaScript - บางส่วนถูกกำหนดให้เป็นส่วนหนึ่งของ API ของเบราว์เซอร์ ซึ่งสร้างขึ้นจากภาษาเริ่มต้นเพื่อให้มีฟังก์ชันการทำงานที่มากยิ่งขึ้น (โปรดดูส่วนแรกของหลักสูตรของเราสำหรับคำอธิบายเพิ่มเติม) เราจะดูการใช้ API ของเบราว์เซอร์โดยละเอียดในโมดูลถัดไป
ฟังก์ชันเทียบกับวิธีการสิ่งหนึ่งที่เราต้องเคลียร์ก่อนที่จะดำเนินการต่อ - ในทางเทคนิคแล้ว ฟังก์ชันเบราว์เซอร์ในตัวไม่ใช่ฟังก์ชัน - แต่เป็นวิธีการ ฟังดูน่ากลัวและสับสนเล็กน้อย แต่อย่ากังวล คำว่าฟังก์ชันและวิธีการส่วนใหญ่ใช้แทนกันได้ อย่างน้อยก็เพื่อจุดประสงค์ของเราในขั้นตอนการเรียนรู้ของคุณ
ความแตกต่างก็คือวิธีการเป็นฟังก์ชันที่กำหนดไว้ภายในวัตถุ ฟังก์ชัน (วิธีการ) และตัวแปรของเบราว์เซอร์ในตัว (ซึ่งเรียกว่า properties ) จะถูกจัดเก็บไว้ในวัตถุที่มีโครงสร้าง เพื่อให้โค้ดมีประสิทธิภาพและจัดการได้ง่ายขึ้น
คุณไม่จำเป็นต้องเรียนรู้เกี่ยวกับการทำงานภายในของออบเจ็กต์ JavaScript ที่มีโครงสร้าง แต่คุณสามารถรอจนถึงโมดูลถัดไปของเราที่จะสอนคุณเกี่ยวกับการทำงานภายในของออบเจ็กต์ และวิธีการสร้าง ของคุณเอง- สำหรับตอนนี้ เราเพียงต้องการเคลียร์ความสับสนที่อาจเกิดขึ้นระหว่างวิธีการและฟังก์ชัน - คุณน่าจะมีคุณสมบัติตรงตามทั้งสองเงื่อนไขเมื่อคุณดูแหล่งข้อมูลที่เกี่ยวข้องที่มีอยู่ทั่วทั้งเว็บ
ฟังก์ชั่นที่กำหนดเองจนถึงตอนนี้คุณเคยเห็นฟังก์ชันที่กำหนดเองมากมายในหลักสูตร - ฟังก์ชั่นที่กำหนดไว้ในโค้ดของคุณ ไม่ใช่ในเบราว์เซอร์ เมื่อใดก็ตามที่คุณเห็นชื่อที่กำหนดเองโดยมีวงเล็บต่อจากนั้น แสดงว่าคุณกำลังใช้ฟังก์ชันที่กำหนดเอง ในการสุ่มของเรา ตัวอย่าง canvas-circles.html (ดูทั้งหมด) จากบทความลูปของเรา เราได้รวมฟังก์ชัน Draw() แบบกำหนดเองที่มีลักษณะดังนี้:
ฟังก์ชั่นวาด() ( ctx.clearRect(0,0,WIDTH,HEIGHT); for (var i = 0; i< 100; i++) { ctx.beginPath(); ctx.fillStyle = "rgba(255,0,0,0.5)"; ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI); ctx.fill(); } }
ฟังก์ชั่นนี้จะสุ่มวงกลม 100 วงภายในองค์ประกอบ ทุกครั้งที่เราต้องการทำสิ่งนั้น เราก็สามารถเรียกใช้ฟังก์ชันด้วยสิ่งนี้ได้
แทนที่จะต้องเขียนโค้ดนั้นทั้งหมดอีกครั้งทุกครั้งที่เราต้องการทำซ้ำ และฟังก์ชันต่างๆ สามารถมีโค้ดอะไรก็ได้ที่คุณต้องการ - คุณสามารถเรียกใช้ฟังก์ชันอื่นๆ จากฟังก์ชันภายในได้ ตัวอย่างฟังก์ชันข้างต้นเรียกใช้ฟังก์ชัน Random() สามครั้ง ซึ่งกำหนดโดย ต่อไปนี้รหัส:
ฟังก์ชั่นสุ่ม(ตัวเลข) ( return Math.floor(Math.random()*number); )
เราต้องการฟังก์ชันนี้เนื่องจากฟังก์ชัน Math.random() ในตัวของเบราว์เซอร์สร้างเฉพาะตัวเลขทศนิยมแบบสุ่มระหว่าง 0 ถึง 1 เท่านั้น เราต้องการตัวเลขสุ่มจำนวนเต็มระหว่าง 0 ถึงตัวเลขที่ระบุ
การเรียกใช้ฟังก์ชันตอนนี้คุณคงเข้าใจเรื่องนี้ชัดเจนแล้ว แต่ในกรณีที่ ... หากต้องการใช้ฟังก์ชันจริงหลังจากที่ถูกกำหนดแล้ว คุณจะต้องเรียกใช้ - หรือเรียกใช้ - มัน ซึ่งทำได้โดยการใส่ชื่อของฟังก์ชันใน รหัสอยู่ที่ไหนสักแห่ง ตามด้วยวงเล็บ
ฟังก์ชั่น myFunction() ( alert("hello"); ) myFunction() // เรียกใช้ฟังก์ชันหนึ่งครั้ง
ฟังก์ชั่นที่ไม่ระบุชื่อคุณอาจเห็นฟังก์ชันที่กำหนดและเรียกใช้ในลักษณะที่แตกต่างกันเล็กน้อย จนถึงตอนนี้เราเพิ่งสร้างฟังก์ชั่นดังนี้:
ฟังก์ชั่น myFunction() ( alert("hello"); )
แต่คุณสามารถสร้างฟังก์ชันที่ไม่มีชื่อได้:
ฟังก์ชั่น() ( alert("hello"); )
สิ่งนี้เรียกว่าฟังก์ชันที่ไม่ระบุชื่อ - ไม่มีชื่อ! นอกจากนี้ยังจะไม่ทำอะไรเลย โดยทั่วไปคุณใช้ฟังก์ชันที่ไม่ระบุชื่อพร้อมกับตัวจัดการเหตุการณ์ ตัวอย่างเช่น ฟังก์ชันต่อไปนี้จะเรียกใช้โค้ดภายในฟังก์ชันทุกครั้งที่มีการคลิกปุ่มที่เกี่ยวข้อง:
Var myButton = document.querySelector("ปุ่ม"); myButton.onclick = function() ( alert("hello"); )
ตัวอย่างข้างต้นจะต้องมีองค์ประกอบบนเพจเพื่อเลือกและคลิก คุณเคยเห็นโครงสร้างนี้มาสองสามครั้งตลอดหลักสูตร และจะได้เรียนรู้เพิ่มเติมและดูการใช้งานในบทความถัดไป
คุณยังสามารถกำหนดฟังก์ชันที่ไม่ระบุชื่อให้เป็นค่าของตัวแปรได้ เช่น:
ตัวแปร myGreeting = function() ( alert("hello"); )
ตอนนี้สามารถเรียกใช้ฟังก์ชันนี้ได้โดยใช้:
MyGreeting();
สิ่งนี้ทำให้ชื่อฟังก์ชันมีประสิทธิภาพ คุณยังสามารถกำหนดให้ฟังก์ชันเป็นค่าของตัวแปรหลายตัวได้ เช่น
Var anotherGreeting = function() ( alert("hello"); )
ขณะนี้สามารถเรียกใช้ฟังก์ชันนี้โดยใช้อย่างใดอย่างหนึ่ง
MyGreeting(); อีกคำทักทาย();
แต่นี่อาจทำให้เกิดความสับสน ดังนั้นอย่าทำ! เมื่อสร้างฟังก์ชัน จะเป็นการดีกว่าถ้าใช้แบบฟอร์มนี้:
ฟังก์ชั่น myGreeting() ( alert("hello"); )
คุณจะใช้ฟังก์ชันที่ไม่ระบุตัวตนเป็นหลักเพื่อรันโค้ดจำนวนมากเพื่อตอบสนองต่อเหตุการณ์ที่เริ่มทำงาน เช่น การคลิกปุ่ม โดยใช้ตัวจัดการเหตุการณ์ อีกครั้งสิ่งนี้มีลักษณะดังนี้:
MyButton.onclick = function() ( alert("hello"); // ฉันสามารถใส่โค้ดได้มากเท่าไร // ข้างในนี้ได้ตามต้องการ )
พารามิเตอร์ฟังก์ชันฟังก์ชั่นบางอย่างจำเป็นต้องระบุพารามิเตอร์เมื่อคุณเรียกใช้ - นี่คือค่าที่ต้องรวมไว้ในวงเล็บของฟังก์ชันซึ่งจำเป็นต้องทำงานอย่างถูกต้อง
หมายเหตุ : บางครั้งพารามิเตอร์เรียกว่าอาร์กิวเมนต์ คุณสมบัติ หรือแม้แต่แอตทริบิวต์
ตามตัวอย่าง ฟังก์ชัน Math.random() ในตัวของเบราว์เซอร์ไม่จำเป็นต้องใช้พารามิเตอร์ใดๆ เมื่อเรียกจะส่งกลับตัวเลขสุ่มระหว่าง 0 ถึง 1 เสมอ:
วาร์ myNumber = Math.random();
อย่างไรก็ตาม ฟังก์ชันสตริงแทนที่ () ในตัวของเบราว์เซอร์จำเป็นต้องมีพารามิเตอร์สองตัว ได้แก่ สตริงย่อยที่จะค้นหาในสตริงหลัก และสตริงย่อยเพื่อแทนที่สตริงนั้นด้วย:
Var myText = "ฉันเป็นสตริง"; var newString = myText.replace("string", "ไส้กรอก");
หมายเหตุ : เมื่อคุณต้องการระบุพารามิเตอร์หลายตัว พารามิเตอร์เหล่านั้นจะถูกคั่นด้วยเครื่องหมายจุลภาค
ควรสังเกตว่าบางครั้งพารามิเตอร์ก็เป็นทางเลือก - คุณไม่จำเป็นต้องระบุพารามิเตอร์เหล่านั้น ถ้าคุณไม่ระบุ โดยทั่วไปฟังก์ชันจะใช้พฤติกรรมเริ่มต้นบางประเภท ตามตัวอย่าง พารามิเตอร์ของฟังก์ชัน array join() เป็นทางเลือก:
Var myArray = ["ฉัน", "ความรัก", "ช็อคโกแลต", "กบ"]; var madeAString = myArray.join(" "); // ส่งกลับ "ฉันรักกบช็อคโกแลต" var madeAString = myArray.join(); // ส่งกลับ "ฉันรักช็อคโกแลตกบ"
หากไม่มีพารามิเตอร์เพื่อระบุอักขระที่รวม/คั่น ระบบจะใช้ลูกน้ำเป็นค่าเริ่มต้น
ขอบเขตการทำงานและข้อขัดแย้งมาพูดถึงขอบเขตกันสักหน่อย - แนวคิดที่สำคัญมากในการจัดการกับฟังก์ชัน เมื่อคุณสร้างฟังก์ชัน ตัวแปรและสิ่งอื่น ๆ ที่กำหนดไว้ภายในฟังก์ชันจะอยู่ภายในขอบเขตที่แยกจากกัน ซึ่งหมายความว่าพวกมันจะถูกล็อคไว้ในช่องที่แยกจากกัน ไม่สามารถเข้าถึงได้จากภายในฟังก์ชันอื่นหรือจากโค้ดภายนอกฟังก์ชัน
ระดับบนสุดที่อยู่นอกฟังก์ชันทั้งหมดของคุณเรียกว่าขอบเขตส่วนกลาง ค่าที่กำหนดในขอบเขตส่วนกลางสามารถเข้าถึงได้จากทุกที่ในโค้ด
JavaScript ได้รับการตั้งค่าเช่นนี้ด้วยเหตุผลหลายประการ - แต่ส่วนใหญ่เป็นเพราะความปลอดภัยและการจัดองค์กร บางครั้งคุณไม่ต้องการให้ตัวแปรสามารถเข้าถึงได้จากทุกที่ในโค้ด - สคริปต์ภายนอกที่คุณเรียกใช้จากที่อื่นอาจเริ่มยุ่งกับโค้ดของคุณและทำให้เกิดปัญหาเนื่องจากสคริปต์เหล่านั้นใช้ชื่อตัวแปรเดียวกันกับส่วนอื่น ๆ ของโค้ด ทำให้เกิดความขัดแย้งซึ่งอาจกระทำโดยเจตนาร้ายหรือเพียงบังเอิญ
ตัวอย่างเช่น สมมติว่าคุณมีไฟล์ HTML ที่เรียกใช้ไฟล์ JavaScript ภายนอกสองไฟล์ และทั้งสองไฟล์มีตัวแปรและฟังก์ชันที่กำหนดให้ใช้ชื่อเดียวกัน:
การทักทาย(); // first.js var name = "คริส"; ฟังก์ชั่น คำทักทาย() ( alert("Hello " + name + ": ยินดีต้อนรับสู่บริษัทของเรา"); ) // Second.js var name = "Zaptec"; ฟังก์ชั่น คำทักทาย() ( alert("บริษัทของเราชื่อ " + name + "."); )
ทั้งสองฟังก์ชันที่คุณต้องการเรียกใช้เรียกว่า Greeting() แต่คุณสามารถเข้าถึงฟังก์ชัน Greeting() ของไฟล์ Second.js ได้เท่านั้น โดยจะถูกนำไปใช้กับ HTML ในภายหลังในซอร์สโค้ด ดังนั้นตัวแปรและฟังก์ชันจึงเขียนทับ ที่อยู่ใน first.js
การล็อคโค้ดบางส่วนไว้ในฟังก์ชันจะช่วยหลีกเลี่ยงปัญหาดังกล่าว และถือเป็นแนวปฏิบัติที่ดีที่สุด
มันเหมือนกับสวนสัตว์นิดหน่อย สิงโต ม้าลาย เสือ และนกเพนกวินจะถูกเก็บไว้ในกรงของพวกมันเอง และจะเข้าถึงได้เฉพาะสิ่งของที่อยู่ภายในกรงเท่านั้น ในลักษณะเดียวกับขอบเขตการใช้งาน หากเข้าไปในกรงอื่นได้ ปัญหาก็จะเกิดตามมา อย่างดีที่สุด สัตว์ต่างๆ จะรู้สึกไม่สบายใจจริงๆ ในถิ่นที่อยู่ที่ไม่คุ้นเคย สิงโตหรือเสือจะรู้สึกแย่เมื่ออยู่ในพื้นที่ที่เป็นน้ำแข็งของนกเพนกวิน ที่เลวร้ายที่สุด สิงโตและเสืออาจพยายามกินนกเพนกวิน!
ผู้ดูแลสวนสัตว์เปรียบเสมือนขอบเขตระดับโลก เขามีกุญแจสำหรับเข้าถึงทุกกรง เติมอาหาร ดูแลสัตว์ป่วย ฯลฯ
การเรียนรู้เชิงรุก: การเล่นอย่างมีขอบเขตมาดูตัวอย่างจริงเพื่อสาธิตการกำหนดขอบเขต
ทั้งการเรียก a() และ b() ควรส่งออกค่า x - 1 สิ่งเหล่านี้ทำงานได้ดีเพราะแม้ว่าการเรียก output() จะไม่อยู่ในขอบเขตเดียวกันกับที่ x กำหนดไว้ แต่ x ก็เป็นตัวแปรร่วมดังนั้นจึงพร้อมใช้งาน ภายในโค้ดทั้งหมดทุกที่
สุดท้ายนี้ ลองอัปเดตโค้ดของคุณดังนี้: function a() ( var y = 2; output(z); ) function b() ( var z = 3; output(y); ) บันทึกและโหลดซ้ำอีกครั้ง และลองอีกครั้ง ในคอนโซล JavaScript ของคุณ: ก(); ข();ซึ่งมันจัดการและส่งกลับผลลัพธ์ ตัวอย่างเช่น ฟังก์ชัน y = 2 * x +5 ตรงนี้เราสามารถกำหนดให้ x = 3 และคำตอบจะเป็น y = 11 นี่คือตัวอย่างฟังก์ชันจากคณิตศาสตร์ มีฟังก์ชันที่คล้ายกันอย่างยิ่งใน JavaScript เฉพาะที่นี่เท่านั้นที่ฟังก์ชันนี้ไม่เพียงแต่คำนวณนิพจน์บางอย่างเท่านั้น แต่ยังเป็นอะไรก็ได้
ขั้นแรกเรามาสร้างฟังก์ชั่นที่แสดงข้อความ "Hello" 3 ครั้งกันก่อน
ฟังก์ชั่นสวัสดี() (
alert("สวัสดี");
alert("สวัสดี");
alert("สวัสดี");
}
สวัสดี();
บรรทัดแรกจะบอกคุณว่าสิ่งต่อไปนี้คือสคริปต์ JavaScript บรรทัดถัดไปประกาศฟังก์ชัน อย่างที่คุณเห็น ทุกอย่างเริ่มต้นด้วยคีย์เวิร์ดของฟังก์ชัน พารามิเตอร์จะแสดงอยู่ในวงเล็บ แต่ในกรณีนี้ไม่มีพารามิเตอร์ ดังนั้นทุกสิ่งในวงเล็บจึงว่างเปล่า ถัดมาคือวงเล็บปีกกา ซึ่งข้างในเป็นโค้ดฟังก์ชันที่ต้องดำเนินการเมื่อมีการเรียกใช้ รหัสนี้ใช้ฟังก์ชัน alert() ซึ่งจะเรียกหน้าต่างข้อมูลซึ่งมีการเขียนข้อความที่ระบุโดยพารามิเตอร์ ในฐานะพารามิเตอร์ เราจะส่งสตริง "Hello" ไปยังฟังก์ชัน alert() (นี่คือตัวอย่างของฟังก์ชันในตัว) เราเรียกฟังก์ชัน alert() สามครั้ง
เมื่อเขียนฟังก์ชันแล้ว คุณจะต้องใส่เครื่องหมายปีกกาปิด บรรทัดถัดไปเราเรียกฟังก์ชัน hello() ฉันหวังว่าคุณจะเข้าใจว่าฟังก์ชันคืออะไร เป็นไปได้ที่พวกคุณบางคนจะถามว่า “มีข้อดีอะไรบ้าง เราสามารถเขียน alert() สามครั้งแล้วผลลัพธ์ก็จะเหมือนเดิม” คุณพูดถูก และนี่คือสิ่งที่คุณควรทำหากคุณต้องการใช้รหัสนี้เพียงครั้งเดียว ลองนึกภาพว่าคุณต้องการสิ่งนี้ 3, 4 หรือมากกว่านั้น แน่นอนว่าการเขียนโค้ดซ้ำๆ ตลอดเวลานั้นไม่สะดวก การเขียนคำเดียวว่า hello() นั้นง่ายกว่ามาก คุณเห็นด้วยไหม? ฉันคิดอย่างนั้น. ในตอนท้ายของบทความฉันจะให้ข้อสรุปที่สำคัญมากอย่างหนึ่งดังนั้นอ่านให้จบ
ตอนนี้เรามาพูดถึงฟังก์ชันที่มีพารามิเตอร์กัน มาสร้างหนึ่งในตัวอย่างเหล่านี้กันดีกว่า (ฉันจะเขียนฟังก์ชันและการเรียกใช้ฟังก์ชันทันที โดยไม่มีแท็ก)
ผลรวมฟังก์ชัน (x, y) (
ผลรวม var = x + y;
document.write(ผลรวม);
}
ผลรวม(5, 4);
รหัสค่อนข้างโปร่งใส แต่ให้ฉันแสดงความคิดเห็น อีกครั้ง คำหลัก function ตามด้วยชื่อของฟังก์ชัน (ในกรณีนี้ ให้เป็นผลรวม) ภายในวงเล็บฉันระบุพารามิเตอร์สองตัวที่จำเป็น ( xและ ย- ภายในฟังก์ชัน ฉันสร้างตัวแปรอื่นขึ้นมา ผลรวม(เป็นเรื่องปกติที่จะตั้งชื่อตัวแปรและฟังก์ชันเหมือนกัน) ซึ่งฉันจะกำหนดผลรวมให้ xและ ย(ซึ่งได้โอนไปแล้ว) จากนั้นฉันก็แสดงผลลัพธ์ในหน้าต่างเบราว์เซอร์ หลังจากฟังก์ชันนี้ ฉันเรียกมันโดยส่งพารามิเตอร์ 5 และ 4 คุณสามารถตรวจสอบและดูได้ในหน้าต่างเบราว์เซอร์ - 9
และสุดท้าย ฉันจะพูดบางอย่างเกี่ยวกับค่าที่ส่งคืน ในตัวอย่างด้านบน เราพิมพ์ผลลัพธ์ทันที อย่างไรก็ตาม สำหรับฟังก์ชันนี้ มีเหตุผลมากที่สุดที่จะไม่พิมพ์อะไรเลย แต่จะส่งคืนผลลัพธ์ จะทำอย่างไรกับมันต่อไปเป็นอีกคำถามหนึ่ง ลองเขียนฟังก์ชันใหม่ดังนี้:
ผลรวมฟังก์ชัน(x, y) (
ผลรวม var = x + y;
จำนวนเงินที่ส่งคืน;
}
var z = ผลรวม(4, 5) + ผลรวม(1,-3);
เอกสาร.write(z);
ให้ความสนใจกับคีย์เวิร์ด return มันจะส่งคืนผลลัพธ์ (ในกรณีของเราคือผลรวมของตัวเลขสองตัว) ดังนั้น sum(4,5) จะส่งกลับ 9 เราเพิ่มตัวเลขนี้เข้ากับผลลัพธ์ของฟังก์ชัน sum(1, -3) นั่นคือ -2 เป็นผลให้เราได้ 7 จากนั้นเราจะพิมพ์ผลลัพธ์ในเบราว์เซอร์เท่านั้น
ฉันหวังว่าคุณจะชื่นชมความสามารถของฟังก์ชันต่างๆ ดังนั้นการสร้างและใช้งานฟังก์ชันใน JavaScript จึงเป็นสิ่งจำเป็น และตอนนี้ฉันจะสรุปสิ่งสำคัญข้อหนึ่ง ซึ่งเป็นหลักการที่ต้องปฏิบัติตามเสมอ: โค้ดที่ซ้ำกันจะต้องแยกออกเป็นฟังก์ชันแยกต่างหาก หากคุณแสดง 5 บรรทัดเดียวกัน 20 ครั้ง (ตัวอย่าง) คุณจะต้องแยก 5 บรรทัดเหล่านี้ออกเป็นฟังก์ชันแยกกัน ดังนั้นแทนที่จะเขียน 100 บรรทัด (20 ครั้ง * 5 บรรทัด) ให้เขียนเพียง 20 บรรทัดและยิ่งเข้าใจได้มากขึ้น (ชื่อของฟังก์ชันนั้นง่ายกว่าโค้ด 5 บรรทัดมาก) ฉันอยากจะบอกว่าหากไม่ปฏิบัติตามกฎนี้ขนาดของโปรแกรมก็สามารถเพิ่มได้หลายสิบหรืออาจเป็นร้อยเท่า
ฉันแนะนำให้คุณฝึกฝนและสร้างฟังก์ชั่นพื้นฐานทั้งหมด การดำเนินการทางคณิตศาสตร์(บวก ลบ คูณ หาร)
เริ่มจากความจริงที่ว่า ภาษาจาวาสคริปต์รองรับแนวคิด OOP (Object Oriented Programming) แนวคิดนี้คือมีองค์ประกอบต่างๆ เช่น วัตถุ และวัตถุเหล่านี้มีคุณสมบัติและวิธีการ (ฟังก์ชัน) ที่หลากหลายที่ช่วยให้คุณสามารถจัดการพวกมันได้
ฟังก์ชันคือบล็อกโค้ดเดียวที่ประกอบด้วยคำสั่งตั้งแต่หนึ่งคำสั่งขึ้นไป มีชื่อเป็นของตัวเอง (ไม่ซ้ำกัน) และสามารถรับพารามิเตอร์ต่างๆ ได้ ขึ้นอยู่กับว่าสามารถดำเนินการใดได้บ้าง
เมธอดก็เป็นฟังก์ชันเช่นกัน แต่มันก็เป็นของคลาสหรืออ็อบเจ็กต์บางตัวอยู่แล้ว
ในการเรียกเมธอดนั้น คุณต้องเขียนชื่อของอ็อบเจ็กต์ก่อน จากนั้นจึงเขียนชื่อของเมธอดโดยคั่นด้วยจุด ข้อยกเว้นสำหรับกฎนี้คือเมื่อเรียกเมธอด alert(), ยืนยัน() และ prompt() ของวัตถุหน้าต่าง สามารถเรียกได้โดยไม่ต้องระบุชื่ออ็อบเจ็กต์ เราคุ้นเคยกับวิธีการเหล่านี้แล้วในบทความนี้
นอกจากนี้ ในบทความก่อนหน้านี้ เราได้แนะนำวิธีการเอาท์พุต document.write() ซึ่งเป็นของอ็อบเจ็กต์ document
ดังนั้นในการเขียนโปรแกรมจึงมีโอกาสที่สำคัญมาก ซึ่งก็คือคุณสามารถสร้างฟังก์ชันของคุณเองได้
ไวยากรณ์ของฟังก์ชันมีลักษณะดังนี้:
ตัวอย่างเช่น เรามาสร้างฟังก์ชันง่ายๆ ที่จะเพิ่มข้อความที่ส่งไปยังย่อหน้าและแสดงข้อความนั้น และมันยังจะทำให้เป็นตัวหนาและตัวเอียงด้วย
ฟังก์ชั่น writeText(text)( //เพิ่มข้อความในย่อหน้าแล้วแสดง document.write("
"+ข้อความ+"
"); ) //เรียกใช้ฟังก์ชันที่สร้างขึ้น writeText("Hello!");บันทึกเอกสารและเปิดในเบราว์เซอร์
แสดงความคิดเห็น! เมื่อประกาศฟังก์ชัน ต้องมีเครื่องหมายปีกกาอยู่ ไม่ว่าจะมีโอเปอเรเตอร์กี่ตัวก็ตาม
ฟังก์ชั่นที่จำเป็นในการเขียนโปรแกรมมีอะไรบ้าง?ข้อได้เปรียบหลักของการใช้ฟังก์ชันนี้คือการลดขนาดของซอร์สโค้ดสคริปต์
สมมติว่าเราจำเป็นต้องวนซ้ำอาร์เรย์หนึ่งมิติสามมิติ ดังที่เราทราบจากบทความนี้: อาร์เรย์จะถูกวนซ้ำโดยใช้การวนซ้ำ หากไม่มีฟังก์ชัน โค้ดสำหรับสคริปต์นี้จะมีลักษณะดังนี้:
//ประกาศสามอาร์เรย์ var arr1 = ; วาร์ arr2 = ["b", 5, 9.2, "h", 8, 2]; วาร์ arr2 = ; สำหรับ (var i = 0; i< arr1.length; i++){ document.write("
องค์ประกอบอาร์เรย์ arr1 โดยมีดัชนี " + i + " เท่ากับ: "+ arr1[i] +"
"); ) สำหรับ(var i = 0; i< arr2.length; i++){ document.write("องค์ประกอบอาร์เรย์ arr2 ที่มีดัชนี " + i + " เท่ากับ: "+ arr2[i] +"
"); ) สำหรับ(var i = 0; i< arr3.length; i++){ document.write("องค์ประกอบอาร์เรย์ arr3 ที่มีดัชนี " + i + " เท่ากับ: "+ arr3[i] +"
"); }ดังนั้น เพื่อไม่ให้เขียนลูปของคุณเองสำหรับแต่ละอาเรย์ จะดีกว่าถ้าใช้ฟังก์ชันที่เราส่งผ่านอาเรย์ และมันจะแสดงองค์ประกอบทั้งหมดบนหน้าจอ ด้วยวิธีนี้ ประการแรก เราจะลดขนาดโค้ด และประการที่สอง เราจะกำจัดโค้ดที่ซ้ำกัน
ฟังก์ชัน printArr(arr)( for(var i = 0; i< arr.length; i++){ document.write("
องค์ประกอบอาร์เรย์ที่มีดัชนี " + i + " เท่ากับ: "+ arr[i] +"
"); ) ) // ประกาศสามอาร์เรย์ var arr1 = ; var arr2 = ["b", 5, 9.2, "h", 8, 2]; var arr2 = ; // เรียกใช้ฟังก์ชันที่สร้างขึ้นเพื่อวนซ้ำแต่ละอาร์เรย์ printArr (arr1); printArr (arr2);พารามิเตอร์ฟังก์ชันฟังก์ชันสามารถรับพารามิเตอร์จำนวนเท่าใดก็ได้ ตั้งแต่หนึ่งจนถึงอนันต์ หรืออาจสมบูรณ์โดยไม่มีพารามิเตอร์ก็ได้
มาสร้างฟังก์ชันแบบไม่มีพารามิเตอร์ที่พิมพ์วลี "Hello world" แบบคลาสสิกลงบนหน้าจอกันดีกว่า
ฟังก์ชั่น helloWorld())( document.write("Hello World"); ) // เรียกใช้ฟังก์ชันโดยไม่มีพารามิเตอร์ helloWorld helloWorld();
พารามิเตอร์ฟังก์ชันใดๆ สามารถมีค่าเริ่มต้นของตัวเองได้
ซึ่งหมายความว่าหากเราไม่ส่งค่าใดๆ ไปยังพารามิเตอร์นี้เมื่อเรียกใช้ฟังก์ชัน มันจะใช้ค่าเริ่มต้น
ตัวอย่างเช่น เรามาสร้างฟังก์ชันที่บวกตัวเลขที่ผ่านสองจำนวนกัน หากเราส่งผ่านเพียงตัวเลขเดียว ตามค่าเริ่มต้น ตัวเลขที่สองจะเป็น 4
ฟังก์ชัน summa(number1, number2 = 4)( document.write("
ผลรวมของตัวเลข " + number1 + "(พารามิเตอร์แรก) และ" + number2 + "(พารามิเตอร์ที่สอง) เท่ากับ: " + (number1 + number2) + ""); ) // เรียกใช้ฟังก์ชันที่โดยค่าเริ่มต้นจะส่งออกผลลัพธ์ของการเพิ่มหมายเลขที่ส่งผ่านด้วยหมายเลข 4 summa(5); // ผลลัพธ์: 9 // ถ้าเราระบุพารามิเตอร์ตัวที่สองด้วย ฟังก์ชั่นจะแสดงผลลัพธ์ของการบวกตัวเลขจากพารามิเตอร์ทั้งสอง .summa(5, 20); // ผลลัพธ์: 25
อาจเป็นไปได้ว่าภายในฟังก์ชันสามารถเรียกใช้ฟังก์ชันอื่นที่มีอยู่ได้ ตัวอย่างเช่น ลองเรียกใช้ฟังก์ชัน writeText() แรกที่เราสร้างขึ้นภายในฟังก์ชั่นก่อนหน้า
สรุป() เราจะส่งต่อผลลัพธ์ของการเพิ่มตัวเลขให้กับฟังก์ชัน writeText() ในกรณีนี้ โค้ดสำหรับฟังก์ชัน summa() จะมีลักษณะดังนี้:
ฟังก์ชั่น summa(number1, number2 = 4)( writeText(number1 + number2); ) //เรียกใช้ฟังก์ชัน summa summa(5); // ผลลัพธ์: 9 ผลรวม (5, 20); // ผลลัพธ์: 25ฟังก์ชั่นที่คืนค่าบางอย่าง
จนถึงขณะนี้เรามีฟังก์ชั่นการเขียนที่แสดงผลลัพธ์บนหน้าจอทันที
ตอนนี้เรามาเรียนรู้วิธีเขียนฟังก์ชันที่ให้ผลลัพธ์กลับมา เราสามารถเพิ่มผลลัพธ์นี้ให้กับตัวแปรบางตัวและทำงานกับมันต่อไปได้
เพื่อให้เข้าใจสิ่งที่เรากำลังพูดถึงได้ดีขึ้น เรามาจำวิธีการต่างๆ เช่น prompt() และ ยืนยัน() วิธีการเหล่านี้คืนค่าที่ได้รับจากผู้ใช้จริง ๆ แทนที่จะแสดง
ตัวอย่างเช่น เรามาสร้างฟังก์ชันของเราเองที่จะส่งคืนองค์ประกอบสุดท้ายของอาร์เรย์ที่ส่งผ่านเป็นพารามิเตอร์
ด้วยเหตุนี้ เราจึงได้คำว่า 'twix' เนื่องจากคำนี้เป็นองค์ประกอบสุดท้ายของอาร์เรย์ otherArr
เมธอด alert() จะไม่ส่งคืนสิ่งใด นั่นคือถ้าเราพยายามแสดงตัวแปรที่มีประเภทมีผลของการเรียกเมธอด alert() เราจะเห็นค่า undefinition นี่เหมือนกับการพยายามแสดงค่าของตัวแปรว่าง
ตัวอย่างเช่น ลองนำผลลัพธ์ของการเรียก alert() ครั้งล่าสุดจากตัวอย่างก่อนหน้า มาใส่ในตัวแปร resAlert และใช้ฟังก์ชัน writeText ที่เราสร้างขึ้นเพื่อลองพิมพ์ผลลัพธ์
//แสดงองค์ประกอบสุดท้ายที่ได้รับของอาร์เรย์ var resAlert = alert(lastEl); การทดสอบ var; writeText(resAlert); //ไม่ได้กำหนด writeText(ทดสอบ); //ไม่ได้กำหนด
อย่างที่คุณเห็นในทั้งสองกรณีเราได้รับค่าที่ไม่ได้กำหนด
ตัวแปรโกลบอลและโลคัลตัวแปรโกลบอลคือตัวแปรที่ถูกประกาศนอกฟังก์ชัน นั่นคือตัวแปรทั้งหมดที่ไม่ได้ประกาศภายในฟังก์ชันนั้นเป็นตัวแปรร่วม มองเห็นได้ (ถูกต้อง) ทั่วทั้งเอกสาร
ตัวแปรท้องถิ่นคือตัวแปรที่ถูกประกาศภายในฟังก์ชันนั้นเอง และมันใช้ได้เฉพาะในฟังก์ชันที่กำหนดเท่านั้น ภายนอกตัวแปรภายในเครื่องจะไม่ทำงานอีกต่อไป
ตัวแปรท้องถิ่นและระดับโลกไม่เกี่ยวข้องกันแต่อย่างใด
ในตัวอย่างจากรูปภาพ ถ้าเราพยายามแสดงเนื้อหาของตัวแปร x เราจะได้รับข้อความที่ไม่ได้กำหนดเนื่องจากเราลืมเรียกใช้ฟังก์ชัน other()
ดังนั้นเพื่อให้การเปลี่ยนแปลงที่เกิดขึ้นภายในฟังก์ชันทำงานได้ จำเป็นต้องเรียกใช้ฟังก์ชันนี้
เราเรียกฟังก์ชัน other() และถ้าเราพยายามแสดงค่าของตัวแปร x เราจะเห็นผลลัพธ์เป็นเลข 4
หากต้องการเข้าถึงตัวแปรโกลบอลจากภายในฟังก์ชัน คุณไม่จำเป็นต้องทำอะไรเลย คุณเพียงแค่ต้องใช้มันเท่านั้น การเปลี่ยนแปลงที่ทำกับตัวแปรส่วนกลางจะมองเห็นได้ภายนอกฟังก์ชัน
วาร์ x = 8; เพิ่มฟังก์ชัน() ( x++; ) //เรียกฟังก์ชันเพิ่ม() เพิ่มค่า(); การแจ้งเตือน(x); //ผลลัพธ์: 9
หากเราไม่ต้องการให้ตัวแปรส่วนกลางเปลี่ยนแปลง เราต้องประกาศตัวแปรท้องถิ่น (อาจมีชื่อเดียวกับตัวแปรส่วนกลาง) และการดำเนินการทั้งหมดจะดำเนินการกับตัวแปรนั้น
วาร์ ก = 100; function func())( var g = 14; g *= 2; // นี่เหมือนกับ g = g * 2 alert(g); // ผลลัพธ์: 28 ) // เรียกใช้ฟังก์ชัน ฟังก์ชั่น(); alert(g);//ผลลัพธ์: 100
เพียงเท่านี้ ผู้อ่านที่รัก ตอนนี้คุณรู้แล้วว่าฟังก์ชันคืออะไร วิธีสร้างฟังก์ชันของคุณเอง วิธีเรียกใช้ฟังก์ชัน และประเภทของฟังก์ชันที่มีอยู่ คุณยังได้เรียนรู้ว่าตัวแปรระดับโลกและตัวแปรท้องถิ่นคืออะไร
อย่างที่ฉันเขียนไว้ตอนต้นของบทความ ฟังก์ชั่นต่างๆ นั้นดีมาก องค์ประกอบที่สำคัญดังนั้นคุณควรจะรู้จักพวกเขาอย่างถ่องแท้
งาน- จาวาสคริปต์
- การแปล
ฉันมักจะเจอโค้ด JavaScript ซึ่งข้อผิดพลาดเกิดจากความเข้าใจผิดเกี่ยวกับวิธีการทำงานของฟังก์ชันใน JavaScript (โดยส่วนใหญ่โค้ดนี้เขียนโดยฉันเอง) JavaScript เป็นภาษาที่มีหลายกระบวนทัศน์ และมีกลไกการเขียนโปรแกรมที่ใช้งานได้ ถึงเวลาสำรวจความเป็นไปได้เหล่านี้แล้ว ในบทความนี้ ฉันจะบอกคุณห้าวิธีในการเรียกใช้ฟังก์ชันใน JavaScript
ในช่วงแรกของการเรียนรู้ JavaScript ผู้เริ่มต้นมักจะคิดว่าฟังก์ชันในนั้นทำงานในลักษณะเดียวกับใน C# แต่กลไกในการเรียกใช้ฟังก์ชันใน JavaScript มีความแตกต่างที่สำคัญหลายประการ และการเพิกเฉยต่อกลไกเหล่านี้อาจทำให้เกิดข้อผิดพลาดซึ่งหาไม่ได้ง่าย
เรามาเขียนฟังก์ชันง่ายๆ ที่ส่งคืนอาร์เรย์ขององค์ประกอบ 3 รายการ ได้แก่ ค่าปัจจุบันและอาร์กิวเมนต์ทั้งสองที่ส่งไปยังฟังก์ชัน
ฟังก์ชั่น makeArray(arg1, arg2)( return [ this, arg1, arg2 ]; )
makeArray("หนึ่ง", "สอง"); // => [ หน้าต่าง "หนึ่ง", "สอง" ]
รอ. วัตถุหน้าต่างมาจากไหน? ทำไมมันถึงเท่ากับหน้าต่าง?
ใน JavaScript ไม่ว่าสคริปต์จะถูกเรียกใช้งานในเบราว์เซอร์หรือในสภาพแวดล้อมอื่นก็ตาม สคริปต์นั้นจะถูกกำหนดไว้เสมอ วัตถุระดับโลก- รหัสใดๆ ในสคริปต์ของเราที่ไม่ได้ "ผูกมัด" กับสิ่งใดๆ (นั่นคือ ภายนอกการประกาศวัตถุ) จริงๆ แล้วอยู่ในบริบทของวัตถุส่วนกลาง ในกรณีของเรา makeArray ไม่ใช่แค่ฟังก์ชัน "การเดิน" ด้วยตัวมันเอง ในความเป็นจริง makeArray เป็นวิธีการของหน้าต่างอ็อบเจ็กต์โกลบอล (ในกรณีของการเรียกใช้โค้ดในเบราว์เซอร์) ง่ายที่จะพิสูจน์:
การแจ้งเตือน (ประเภทของ window.methodThatDoesntExist); // => การแจ้งเตือนที่ไม่ได้กำหนด (typeof window.makeArray); // => ฟังก์ชั่น
นั่นคือการเรียก makeArray("one", "two"); เทียบเท่ากับการเรียก window.makeArray("one", "two"); -
มันทำให้ฉันเสียใจที่นี่เป็นวิธีการเรียกใช้ฟังก์ชันที่ใช้บ่อยที่สุด เพราะมันบอกเป็นนัยถึงการมีอยู่ของฟังก์ชันโกลบอล และเราทุกคนรู้ดีว่าฟังก์ชันและตัวแปรโกลบอลไม่ใช่รูปแบบที่ดีที่สุดในการเขียนโปรแกรม นี่เป็นเรื่องจริงโดยเฉพาะอย่างยิ่งสำหรับ JavaScript หลีกเลี่ยงคำจำกัดความสากลแล้วคุณจะไม่เสียใจ
กฎการเรียกใช้ฟังก์ชัน #1: หากเรียกใช้ฟังก์ชันโดยตรงโดยไม่ระบุวัตถุ (เช่น myFunction()) ค่าของสิ่งนี้จะเป็นวัตถุส่วนกลาง (หน้าต่างหากโค้ดถูกเรียกใช้งานในเบราว์เซอร์)
การเรียกเมธอด มาสร้างออบเจ็กต์อย่างง่ายและทำให้ makeArray เป็นเมธอดของมันกันดีกว่า เรามาประกาศวัตถุโดยใช้สัญกรณ์ตามตัวอักษรแล้วเรียกวิธีการของเรา:// สร้างวัตถุ var arrayMaker = ( someProperty: "บางค่า", make: makeArray ); // เรียกใช้เมธอด make() arrayMaker.make("one", "two"); // => [ arrayMaker, "one", "two" ] // ไวยากรณ์ทางเลือก, ใช้วงเล็บเหลี่ยม arrayMaker["make"]("one", "two"); // => [ arrayMaker, "หนึ่ง", "สอง" ]
คุณเห็นความแตกต่างหรือไม่? ค่าในกรณีนี้คือตัววัตถุเอง ทำไมไม่ window เหมือนในกรณีก่อนหน้านี้เนื่องจากการประกาศฟังก์ชั่นไม่มีการเปลี่ยนแปลง? เคล็ดลับคือวิธีการส่งผ่านฟังก์ชันต่างๆ ใน JavaScript ฟังก์ชันเป็นประเภท JavaScript มาตรฐานที่เป็นวัตถุจริงๆ และเช่นเดียวกับวัตถุอื่นๆ ฟังก์ชันสามารถส่งผ่านและคัดลอกได้ ในกรณีนี้ เราได้คัดลอกฟังก์ชันทั้งหมดแล้ว รวมถึงรายการอาร์กิวเมนต์และเนื้อหา และกำหนดวัตถุผลลัพธ์ให้กับคุณสมบัติ make ของวัตถุ arrayMaker นี่เทียบเท่ากับการประกาศเช่นนี้:
var arrayMaker = ( someProperty: "ค่าบางอย่าง"; make: function (arg1, arg2) ( return [ this, arg1, arg2]; ) );
กฎการเรียกใช้ฟังก์ชัน #2: ในฟังก์ชันที่เรียกว่าโดยใช้ไวยากรณ์การเรียกเมธอด เช่น obj.myFunction() หรือ obj["myFunction"]() สิ่งนี้จะมีค่า obj
ความเข้าใจผิดเกี่ยวกับหลักการง่ายๆ โดยทั่วไปนี้มักนำไปสู่ข้อผิดพลาดเมื่อประมวลผลเหตุการณ์:
function buttonClicked())( var text = (this === window) ? "window" : this.id; alert(text); ) var button1 = document.getElementById("btn1"); var button2 = document.getElementById("btn2"); button1.onclick = ปุ่มคลิก; button2.onclick = ฟังก์ชั่น())( ปุ่มคลิก(); );
การคลิกปุ่มแรกจะแสดงข้อความ "btn1"เพราะในกรณีนี้ เรากำลังเรียกใช้ฟังก์ชันเป็นเมธอด และสิ่งนี้ภายในฟังก์ชันจะได้รับค่าของอ็อบเจ็กต์ที่เป็นของเมธอดนี้ การคลิกปุ่มที่สองจะให้ "หน้าต่าง"เพราะในกรณีนี้เรากำลังเรียก buttonClicked โดยตรง (เช่น ไม่เหมือนกับ obj.buttonClicked()) สิ่งเดียวกันนี้จะเกิดขึ้นเมื่อเรากำหนดตัวจัดการเหตุการณ์ให้กับแท็กองค์ประกอบ เช่นเดียวกับในกรณีของปุ่มที่สาม การคลิกปุ่มที่สามจะแสดงข้อความเดียวกันกับปุ่มที่สอง
เมื่อใช้ไลบรารีเช่น jQuery คุณไม่จำเป็นต้องคิดถึงเรื่องนี้ jQuery จะดูแลเขียนค่านี้ใหม่ในตัวจัดการเหตุการณ์เพื่อให้ค่านี้เป็นองค์ประกอบที่ทำให้เกิดเหตุการณ์:
// ใช้ jQuery $("#btn1").click(function() ( alert(this.id); // jQuery จะตรวจสอบให้แน่ใจว่า "นี่คือปุ่ม" ));
อะไร วิธี jQueryเป็นไปได้ไหมที่จะเปลี่ยนค่าของสิ่งนี้? อ่านด้านล่าง
var car = ( ปี: 2008 รุ่น: "Dodge Bailout" ); makeArray.apply (รถยนต์, [ "หนึ่ง", "สอง" ]); // => [ รถยนต์ "หนึ่ง", "สอง" ] makeArray.call(รถยนต์ "หนึ่ง", "สอง"); // => [ รถยนต์ "หนึ่ง", "สอง" ]
ทั้งสองวิธีนี้มีความคล้ายคลึงกันมาก พารามิเตอร์แรกจะแทนที่สิ่งนี้ ความแตกต่างระหว่างพวกเขาอยู่ในอาร์กิวเมนต์ที่ตามมา: Function.apply() ยอมรับอาร์เรย์ของค่าที่จะถูกส่งไปยังฟังก์ชัน ในขณะที่ Function.call() ยอมรับอาร์กิวเมนต์แยกกัน ในทางปฏิบัติ ผมว่า Apply() สะดวกกว่านะ
กฎการเรียกใช้ฟังก์ชัน #3: หากคุณต้องการแทนที่ค่านี้โดยไม่คัดลอกฟังก์ชันไปยังอ็อบเจ็กต์อื่น คุณสามารถใช้ myFunction.apply(obj) หรือ myFunction.call(obj)
ฉันจะไม่ลงรายละเอียดเกี่ยวกับการประกาศประเภทที่กำหนดเองใน JavaScript แต่ฉันคิดว่าสิ่งสำคัญคือต้องเตือนคุณว่าไม่มีคลาสใน JavaScript และประเภทที่กำหนดเองใดๆ ก็ตามจำเป็นต้องมีตัวสร้าง นอกจากนี้ เป็นการดีกว่าที่จะประกาศวิธีการประเภทที่กำหนดเองโดยใช้ต้นแบบ ซึ่งเป็นคุณสมบัติของฟังก์ชันตัวสร้าง มาสร้างประเภทของเราเอง:// ประกาศฟังก์ชันคอนสตรัคเตอร์ ArrayMaker(arg1, arg2) ( this.someProperty = "no Matter"; this.theArray = [ this, arg1, arg2 ]; ) // ประกาศวิธีการ ArrayMaker.prototype = ( someMethod: function () ( alert( "ถูกเรียกโดย someMethod"); getArray: function () ( return this.theArray; ) ); var am = new ArrayMaker("หนึ่ง", "สอง"); var other = new ArrayMaker("ครั้งแรก", "วินาที"); am.getArray(); // => [ เช้า "หนึ่ง", "สอง" ]
สิ่งสำคัญในตัวอย่างนี้คือการมีโอเปอเรเตอร์ใหม่อยู่ก่อนการเรียกใช้ฟังก์ชัน หากไม่เป็นเช่นนั้น มันจะเป็นการโทรทั่วโลก และคุณสมบัติที่สร้างขึ้นในตัวสร้างจะเป็นของวัตถุโกลบอล เราไม่ต้องการสิ่งนั้น นอกจากนี้ตัวสร้างมักจะไม่ส่งคืนค่าอย่างชัดเจน หากไม่มีโอเปอเรเตอร์ใหม่ Constructor จะส่งคืน undefinition โดยจะส่งคืนสิ่งนี้ ถือเป็นรูปแบบที่ดีในการตั้งชื่อตัวสร้างด้วยตัวพิมพ์ใหญ่ สิ่งนี้จะเตือนคุณถึงความจำเป็นในการมีโอเปอเรเตอร์ใหม่
มิฉะนั้น โค้ดภายใน Constructor อาจจะคล้ายกับโค้ดที่คุณจะเขียนในภาษาอื่น ค่าในกรณีนี้คือออบเจ็กต์ใหม่ที่คุณกำลังสร้าง
กฎการเรียกใช้ฟังก์ชัน #4: เมื่อเรียกใช้ฟังก์ชันด้วยตัวดำเนินการใหม่ ค่านี้จะเป็นออบเจ็กต์ใหม่ที่สร้างขึ้นโดยสภาพแวดล้อม การดำเนินการจาวาสคริปต์- หากฟังก์ชันนี้ไม่ส่งคืนวัตถุใด ๆ อย่างชัดเจน สิ่งนี้จะถูกส่งคืนโดยปริยาย
หวังว่าการทำความเข้าใจความแตกต่างระหว่างวิธีการเรียกใช้ฟังก์ชันต่างๆ จะช่วยให้คุณปรับปรุงโค้ด JavaScript ของคุณได้ บางครั้งข้อผิดพลาดที่เกี่ยวข้องกับค่านี้เป็นเรื่องยากที่จะตรวจพบ ดังนั้นจึงควรป้องกันไว้ล่วงหน้าฟังก์ชั่นเป็นแนวคิดหลักใน JavaScript คุณสมบัติที่สำคัญที่สุดของภาษาคือการรองรับคุณสมบัติชั้นหนึ่ง (ทำหน้าที่เป็นพลเมืองชั้นหนึ่ง)- ฟังก์ชันใดๆ ก็ตามที่เป็นวัตถุ ดังนั้นจึงสามารถจัดการให้เป็นวัตถุได้ โดยเฉพาะอย่างยิ่ง:
- ส่งผ่านเป็นอาร์กิวเมนต์และส่งกลับเป็นผลเมื่อเรียกใช้ฟังก์ชันอื่น (ฟังก์ชันลำดับที่สูงกว่า)
- สร้างโดยไม่ระบุชื่อและกำหนดค่าให้กับตัวแปรหรือคุณสมบัติของวัตถุ
สิ่งนี้จะกำหนดพลังการแสดงออกที่สูงของ JavaScript และช่วยให้สามารถจัดเป็นหนึ่งในภาษาที่ใช้กระบวนทัศน์การเขียนโปรแกรมเชิงฟังก์ชัน (ซึ่งในตัวมันเองนั้นยอดเยี่ยมมากด้วยเหตุผลหลายประการ)
ฟังก์ชั่นใน JavaScript เป็นอ็อบเจ็กต์ชนิดพิเศษที่ช่วยให้คุณสามารถกำหนดตรรกะของพฤติกรรมและการประมวลผลข้อมูลโดยใช้ภาษาอย่างเป็นทางการ
เพื่อให้เข้าใจถึงวิธีการทำงานของฟังก์ชันต่างๆ จำเป็นต้องมีความเข้าใจในประเด็นต่างๆ ต่อไปนี้ (และเพียงพอ?)
การประกาศฟังก์ชัน ฟังก์ชันในรูปแบบ "คำสั่งการประกาศฟังก์ชัน"ประกาศฟังก์ชัน ( นิยามฟังก์ชัน, หรือ ประกาศฟังก์ชัน, หรือ คำสั่งฟังก์ชัน) ประกอบด้วยคีย์เวิร์ดของฟังก์ชันและส่วนต่างๆ ดังต่อไปนี้:
- ชื่อฟังก์ชัน
- รายการพารามิเตอร์ (ยอมรับโดยฟังก์ชัน) อยู่ในวงเล็บ () และคั่นด้วยเครื่องหมายจุลภาค
- คำแนะนำที่จะดำเนินการหลังจากการเรียกใช้ฟังก์ชันจะอยู่ในวงเล็บปีกกา ( )
ตัวอย่างเช่น รหัสต่อไปนี้ประกาศฟังก์ชันแบบง่ายชื่อ square:
ฟังก์ชั่น สแควร์(หมายเลข) ( หมายเลขส่งคืน * หมายเลข; )
ฟังก์ชัน Square รับหนึ่งพารามิเตอร์ที่เรียกว่าตัวเลข ประกอบด้วยหนึ่งคำสั่งซึ่งหมายถึงการส่งคืนพารามิเตอร์ของฟังก์ชันนี้ (นี่คือตัวเลข) คูณด้วยตัวมันเอง คำสั่ง return ระบุค่าที่ฟังก์ชันจะส่งกลับ
กลับหมายเลข * หมายเลข;
พารามิเตอร์ดั้งเดิม (เช่น ตัวเลข) จะถูกส่งผ่านไปยังฟังก์ชันตามค่า ค่าจะถูกส่งผ่านไปยังฟังก์ชัน แต่ถ้าฟังก์ชันเปลี่ยนค่าของพารามิเตอร์ การเปลี่ยนแปลงนี้จะไม่สะท้อนให้เห็นทั่วโลกหรือหลังจากเรียกใช้ฟังก์ชันแล้ว
หากคุณส่งวัตถุเป็นพารามิเตอร์ (ไม่ใช่วัตถุดั้งเดิม เช่น หรือวัตถุที่ผู้ใช้กำหนด) และฟังก์ชันเปลี่ยนคุณสมบัติของวัตถุที่ส่งผ่านไป การเปลี่ยนแปลงนี้จะมองเห็นได้ภายนอกฟังก์ชัน ดังที่แสดงในตัวอย่างต่อไปนี้ ตัวอย่าง:
ฟังก์ชั่น myFunc(theObject) ( theObject.make = "Toyota"; ) var mycar = (ยี่ห้อ: "Honda", รุ่น: "Accord", ปี: 1998); วาร์ x, y; x = mycar.make; // x รับค่า "Honda" myFunc(mycar); y = mycar.make; // y รับค่า "โตโยต้า" // (คุณสมบัติถูกเปลี่ยนโดยฟังก์ชัน)
หน้าที่ของรูปแบบ "นิพจน์นิยามฟังก์ชัน"ฟังก์ชั่นของรูปแบบ "คำสั่งประกาศฟังก์ชั่น" เป็นคำสั่งในรูปแบบไวยากรณ์ ( คำแถลง) ฟังก์ชันอื่นอาจอยู่ในรูปแบบ "นิพจน์คำจำกัดความของฟังก์ชัน" ฟังก์ชั่นดังกล่าวสามารถไม่ระบุชื่อได้ (ไม่มีชื่อ) ตัวอย่างเช่น ฟังก์ชันสี่เหลี่ยมสามารถเรียกได้ดังนี้:
Var square = function(number) ( return number * number; ); var x = สี่เหลี่ยมจัตุรัส (4); // x ได้รับค่า 16
อย่างไรก็ตาม สามารถกำหนดชื่อให้เรียกตัวเองภายในฟังก์ชันเองและสำหรับดีบักเกอร์ ( ดีบักเกอร์) เพื่อระบุฟังก์ชันในการติดตามสแต็ก ( ร่องรอยสแต็ก- "ติดตาม" - "ติดตาม" / "สำนักพิมพ์")
Var factorial = ฟังก์ชัน fac(n) ( return n< 2 ? 1: n * fac(n - 1); }; console.log(factorial(3));
ฟังก์ชันของรูปแบบ "นิพจน์คำจำกัดความของฟังก์ชัน" มีประโยชน์เมื่อฟังก์ชันถูกส่งผ่านเป็นอาร์กิวเมนต์ไปยังฟังก์ชันอื่น ตัวอย่างต่อไปนี้แสดงฟังก์ชัน map ที่ควรรับฟังก์ชันเป็นอาร์กิวเมนต์แรก และอาร์เรย์เป็นอาร์กิวเมนต์ที่สอง
Function map(f, a) ( var result = , // สร้าง Array ใหม่ i; for (i = 0; i != a.length; i++) result[i] = f(a[i]); return result ; )
ในโค้ดต่อไปนี้ ฟังก์ชันของเรารับฟังก์ชันซึ่งเป็นนิพจน์คำจำกัดความของฟังก์ชัน และดำเนินการกับแต่ละองค์ประกอบของอาร์เรย์ที่ได้รับเป็นอาร์กิวเมนต์ที่สอง
Function map(f, a) ( var result = ; // สร้าง Array ใหม่ var i; // ประกาศตัวแปรสำหรับ (i = 0; i != a.length; i++) result[i] = f(a[i ]); ส่งคืนผลลัพธ์; ) var f = function(x) ( ส่งคืน x * x * x; ) var ตัวเลข = ; var cube = แผนที่ (f, ตัวเลข); console.log(คิวบ์);
ฟังก์ชันส่งคืน: .
ใน JavaScript สามารถประกาศฟังก์ชันโดยมีเงื่อนไขได้ ตัวอย่างเช่น ฟังก์ชันต่อไปนี้จะถูกกำหนดให้กับตัวแปร myFunc หาก num เป็น 0 เท่านั้น:
วาร์ myFunc; ถ้า (num === 0) ( myFunc = function(theObject) ( theObject.make = "Toyota"; ) )
นอกเหนือจากการประกาศฟังก์ชันที่อธิบายไว้ที่นี่ คุณยังสามารถใช้ตัวสร้างฟังก์ชันเพื่อสร้างฟังก์ชันจากสตริง ณ รันไทม์ ( รันไทม์), ชอบ .
วิธีการคือฟังก์ชันที่เป็นคุณสมบัติของวัตถุ คุณสามารถเรียนรู้เพิ่มเติมเกี่ยวกับออบเจ็กต์และวิธีการได้โดยไปที่ลิงก์: การทำงานกับออบเจ็กต์
การเรียกใช้ฟังก์ชันการประกาศฟังก์ชันจะไม่ดำเนินการ การประกาศฟังก์ชันเพียงตั้งชื่อฟังก์ชันและระบุสิ่งที่ต้องทำเมื่อมีการเรียกใช้ฟังก์ชัน การเรียกใช้ฟังก์ชันดำเนินการตามที่ระบุจริงด้วย พารามิเตอร์ที่ระบุ- ตัวอย่างเช่น หากคุณกำหนดฟังก์ชัน square คุณสามารถเรียกมันได้ดังนี้:
สี่เหลี่ยม(5);
คำสั่งนี้เรียกใช้ฟังก์ชันที่มีอาร์กิวเมนต์ 5 ฟังก์ชันเรียกคำสั่งและส่งกลับค่า 25
ฟังก์ชั่นสามารถอยู่ในขอบเขตเมื่อมีการกำหนดไว้แล้ว แต่ฟังก์ชั่นของแบบฟอร์ม "คำสั่งการประกาศฟังก์ชั่น" สามารถยกขึ้นได้ ( เลี้ยง - ยก) เช่นเดียวกับในตัวอย่างนี้:
Console.log (สี่เหลี่ยม (5)); /* ... */ ฟังก์ชั่น สแควร์(n) ( return n * n; )
ขอบเขตของฟังก์ชันคือฟังก์ชันที่ถูกกำหนดไว้หรือ โปรแกรมทั้งหมดหากมีการประกาศในระดับที่สูงกว่า
หมายเหตุ: ใช้งานได้เฉพาะเมื่อการประกาศฟังก์ชันใช้ไวยากรณ์ด้านบน (เช่น ฟังก์ชัน funcName()) รหัสด้านล่างจะไม่ทำงาน ความหมายก็คือ การยกฟังก์ชันใช้งานได้เฉพาะกับการประกาศฟังก์ชันเท่านั้น และไม่ทำงานกับนิพจน์ฟังก์ชัน
Console.log (สี่เหลี่ยมจัตุรัส); // ยกกำลังสองด้วยค่าที่ไม่ได้กำหนด console.log(สี่เหลี่ยม(5)); // TypeError: square ไม่ใช่ฟังก์ชัน var square = function(n) ( return n * n; )
อาร์กิวเมนต์ของฟังก์ชันไม่ได้จำกัดอยู่เพียงสตริงและตัวเลข คุณสามารถส่งวัตถุทั้งหมดไปยังฟังก์ชันได้ ฟังก์ชัน show_props() (ประกาศในการทำงานกับวัตถุ) เป็นตัวอย่างของฟังก์ชันที่รับวัตถุเป็นอาร์กิวเมนต์
ฟังก์ชั่นสามารถเรียกตัวเองได้ ตัวอย่างเช่น นี่คือฟังก์ชันสำหรับคำนวณแฟคทอเรียลแบบวนซ้ำ:
ฟังก์ชัน factorial(n) ( if ((n === 0) || (n === 1)) return 1; else return (n * factorial(n - 1)); )
จากนั้นคุณสามารถคำนวณแฟกทอเรียลจาก 1 ถึง 5 ได้ดังนี้:
วาร์ ก, ข, ค, ง, อี; ก = แฟกทอเรียล (1); // a รับค่า 1 b = แฟกทอเรียล (2); // b รับค่า 2 c = แฟกทอเรียล (3); // c รับค่า 6 d = แฟกทอเรียล (4); // d รับค่า 24 e = factorial(5); //e รับค่า 120
มีวิธีอื่นในการเรียกใช้ฟังก์ชัน มีหลายกรณีที่จำเป็นต้องเรียกใช้ฟังก์ชันแบบไดนามิก หรือจำเป็นต้องเปลี่ยนหมายเลขอาร์กิวเมนต์ของฟังก์ชัน หรือจำเป็นต้องเรียกใช้ฟังก์ชันในบริบทเฉพาะ ปรากฎว่าฟังก์ชันก็คือวัตถุ และวัตถุเหล่านั้นก็มีวิธีการ (ดูวัตถุ) หนึ่งในนั้นคือวิธีการที่สามารถบรรลุเป้าหมายนี้ได้
ขอบเขตของฟังก์ชัน(ขอบเขตฟังก์ชัน)
ตัวแปรที่ประกาศในฟังก์ชันไม่สามารถเข้าถึงได้จากที่อื่นนอกเหนือจากฟังก์ชันนี้ ดังนั้นตัวแปร (ซึ่งจำเป็นสำหรับฟังก์ชันนี้โดยเฉพาะ) จะถูกประกาศในขอบเขตของฟังก์ชันเท่านั้น ในกรณีนี้ ฟังก์ชันสามารถเข้าถึงตัวแปรและฟังก์ชันทั้งหมดที่ประกาศภายในขอบเขตของมัน กล่าวอีกนัยหนึ่ง ฟังก์ชันที่ประกาศในขอบเขตส่วนกลางจะสามารถเข้าถึงตัวแปรทั้งหมดในขอบเขตส่วนกลางได้ ฟังก์ชันที่ประกาศภายในฟังก์ชันอื่นยังสามารถเข้าถึงตัวแปรทั้งหมดของฟังก์ชันพาเรนต์และตัวแปรอื่นๆ ที่ฟังก์ชันพาเรนต์นี้สามารถเข้าถึงได้
// ตัวแปรต่อไปนี้ถูกประกาศในขอบเขตสากล var num1 = 20, num2 = 3, name = "Chamahk"; // ฟังก์ชันนี้ถูกประกาศในฟังก์ชันขอบเขตสากล multiply() ( return num1 * num2; ) multiply(); // จะส่งกลับ 60 // ตัวอย่างของฟังก์ชันที่ซ้อนกัน function getScore() ( var num1 = 2, num2 = 3; function add() ( return name + "scored" + (num1 + num2); ) return add(); ) รับคะแนน( ); // จะกลับมา "ชะมะคะแนน 5"
ขอบเขตและสแต็กฟังก์ชัน(สแต็กฟังก์ชัน)
การเรียกซ้ำฟังก์ชั่นสามารถเรียกตัวเองได้ สามวิธีในการเรียกสิ่งนี้:
ตัวอย่างเช่น พิจารณาฟังก์ชันต่อไปนี้:
Var foo = function bar() ( // คำสั่งไปที่นี่ );
ภายในฟังก์ชัน ( ฟังก์ชั่นร่างกาย) การโทรต่อไปนี้ทั้งหมดเทียบเท่ากัน:
ฟังก์ชันที่เรียกตัวเองเรียกว่า ฟังก์ชันแบบเรียกซ้ำ (ฟังก์ชันแบบเรียกซ้ำ- ปรากฎว่าการเรียกซ้ำนั้นคล้ายกับการวนซ้ำ ( วนซ้ำ- ทั้งสองเรียกโค้ดหลายครั้ง และทั้งคู่ต้องมีเงื่อนไข (เพื่อหลีกเลี่ยง วนซ้ำไม่รู้จบหรือการเรียกซ้ำแบบไม่มีที่สิ้นสุด) ตัวอย่างเช่น วงต่อไปนี้:
วาร์ x = 0; ในขณะที่(x< 10) { // "x < 10" - это условие для цикла // do stuff x++; }
สามารถเปลี่ยนเป็นฟังก์ชันแบบเรียกซ้ำและเรียกใช้ฟังก์ชันนี้ได้:
Function loop(x) ( if (x >= 10) // "x >= 10" เป็นเงื่อนไขสำหรับการสิ้นสุดการดำเนินการ (เหมือนกับ "!(x< 10)") return; // делать что-то loop(x + 1); // рекурсионный вызов } loop(0);
อย่างไรก็ตาม อัลกอริธึมบางตัวไม่สามารถเป็นการวนซ้ำอย่างง่ายได้ ตัวอย่างเช่น การรับองค์ประกอบทั้งหมดของโครงสร้างแบบต้นไม้ (เช่น ) สามารถทำได้ง่ายที่สุดโดยใช้การเรียกซ้ำ:
ฟังก์ชั่น walkTree(node) ( if (node == null) // return; // ทำบางสิ่งกับองค์ประกอบสำหรับ (var i = 0; i< node.childNodes.length; i++) { walkTree(node.childNodes[i]); } }
เมื่อเปรียบเทียบกับฟังก์ชันลูป การเรียกซ้ำแต่ละครั้งจะทำให้เกิดการเรียกซ้ำหลายครั้ง
นอกจากนี้ยังเป็นไปได้ที่จะเปลี่ยนอัลกอริธึมแบบเรียกซ้ำบางส่วนให้เป็นแบบไม่เรียกซ้ำ แต่บ่อยครั้งที่ตรรกะนั้นซับซ้อนมากและจำเป็นต้องใช้สแต็ก ( สแต็ค- ในความเป็นจริง การเรียกซ้ำใช้ stach: function stack
พฤติกรรมของสแต็ก" สามารถดูได้ในตัวอย่างต่อไปนี้:
ฟังก์ชั่น foo(i) ( ถ้า (i< 0) return; console.log("begin: " + i); foo(i - 1); console.log("end: " + i); } foo(3); // Output: // begin: 3 // begin: 2 // begin: 1 // begin: 0 // end: 0 // end: 1 // end: 2 // end: 3
ฟังก์ชั่นและการปิดที่ซ้อนกันคุณสามารถซ้อนฟังก์ชันหนึ่งไว้ภายในอีกฟังก์ชันหนึ่งได้ ฟังก์ชันที่ซ้อนกัน ( ฟังก์ชันที่ซ้อนกัน;ภายใน) ส่วนตัว ( ส่วนตัว) และมันถูกวางไว้ในฟังก์ชันอื่น ( ด้านนอก- นี่คือวิธีที่มันถูกสร้างขึ้น ไฟฟ้าลัดวงจร (ปิด- การปิดคือนิพจน์ (โดยปกติจะเป็นฟังก์ชัน) ที่สามารถมีตัวแปรอิสระได้ พร้อมด้วยสภาพแวดล้อมที่ผูกตัวแปรเหล่านั้น (ซึ่ง "ปิด" ( "ปิด") การแสดงออก).
เนื่องจากฟังก์ชันที่ซ้อนกันเป็นการปิด ซึ่งหมายความว่าฟังก์ชันที่ซ้อนกันสามารถ "สืบทอด" ได้ ( สืบทอด) อาร์กิวเมนต์และตัวแปรของฟังก์ชันที่ซ้อนกันอยู่ กล่าวอีกนัยหนึ่ง ฟังก์ชันที่ซ้อนกันประกอบด้วยขอบเขตของฟังก์ชันภายนอก ( "ด้านนอก") ฟังก์ชัน
สรุป:
- ฟังก์ชันที่ซ้อนกันสามารถเข้าถึงคำสั่งทั้งหมดของฟังก์ชันภายนอกได้
- ฟังก์ชันที่ซ้อนกันจะสร้างการปิด: สามารถใช้อาร์กิวเมนต์และตัวแปรของฟังก์ชันภายนอกได้ ในขณะที่ฟังก์ชันภายนอกไม่สามารถใช้อาร์กิวเมนต์และตัวแปรของฟังก์ชันที่ซ้อนกันได้
ตัวอย่างต่อไปนี้แสดงฟังก์ชันที่ซ้อนกัน:
ฟังก์ชัน addSquares(a, b) ( function square(x) ( return x * x; ) return square(a) + square(b); ) a = addSquares(2, 3); // ส่งคืน 13 b = addSquares(3, 4); // ส่งคืน 25 c = addSquares(4, 5); // คืนค่า 41
เนื่องจากฟังก์ชันที่ซ้อนกันจะสร้างการปิด คุณจึงสามารถเรียกใช้ฟังก์ชันภายนอกและระบุอาร์กิวเมนต์สำหรับทั้งสองฟังก์ชันได้ (ภายนอกและภายใน)
ฟังก์ชั่นภายนอก(x) ( ฟังก์ชั่นภายใน(y) ( กลับ x + y; ) กลับภายใน; ) fn_inside = ภายนอก(3); // ลองคิดดู: ขอฟังก์ชันให้ฉันหน่อย // ที่ผ่าน 3 result = fn_inside(5); // ส่งกลับ 8 result1 = ภายนอก (3) (5); // ส่งคืน 8
การบันทึกตัวแปรโปรดทราบว่าค่าของ x จะถูกรักษาไว้เมื่อส่งคืนค่าภายใน การปิดจะต้องรักษาอาร์กิวเมนต์และตัวแปรไว้ตลอดขอบเขต เนื่องจากการโทรแต่ละครั้งอาจมีข้อโต้แย้งที่แตกต่างกัน การปิดใหม่จึงถูกสร้างขึ้นสำหรับการโทรแต่ละครั้งไปยังภายนอก หน่วยความจำสามารถล้างได้เฉพาะเมื่อภายในกลับมาแล้วและไม่สามารถเข้าถึงได้อีกต่อไป
สิ่งนี้ไม่แตกต่างจากการจัดเก็บการอ้างอิงในออบเจ็กต์อื่น แต่มักจะไม่ชัดเจนเนื่องจากการอ้างอิงไม่ได้ตั้งค่าโดยตรงและไม่สามารถดูได้จากที่นั่น
ฟังก์ชันที่ซ้อนกันแบบทวีคูณสามารถป้อนฟังก์ชันได้หลายครั้ง เช่น ฟังก์ชัน (A) เก็บฟังก์ชัน (B) ซึ่งเก็บฟังก์ชัน (C) การปิดแบบฟอร์มทั้งฟังก์ชัน B และ C ดังนั้น B จึงมีสิทธิ์เข้าถึงตัวแปรและอาร์กิวเมนต์ของ A และ C มีสิทธิ์เข้าถึง B แบบเดียวกัน นอกจากนี้ เนื่องจาก C มีสิทธิ์เข้าถึง B ที่มีสิทธิ์เข้าถึง A แบบเดียวกัน C จึงมีการเข้าถึงเช่นเดียวกัน เข้าถึง A ได้ ดังนั้น cloures สามารถจัดเก็บขอบเขตได้หลายขอบเขต พวกเขาเก็บขอบเขตของฟังก์ชันที่มีอยู่ซ้ำ ๆ มันถูกเรียกว่า การผูกมัด (โซ่ - โซ่- เหตุใดจึงเรียกว่า “การผูกมัด” จะอธิบายภายหลัง)
ลองพิจารณาตัวอย่างต่อไปนี้:
ฟังก์ชัน A(x) ( ฟังก์ชั่น B(y) ( ฟังก์ชั่น C(z) ( console.log(x + y + z); ) C(3); ) B(2); ) A(1); // คอนโซลจะแสดง 6 (1 + 2 + 3)
ในตัวอย่างนี้ C มีสิทธิ์เข้าถึง y ของฟังก์ชัน B และ x ของฟังก์ชัน A สิ่งนี้เกิดขึ้นเพราะ:
ใน ลำดับย้อนกลับอย่างไรก็ตาม สิ่งนี้ไม่เป็นความจริง A ไม่สามารถเข้าถึงตัวแปรและอาร์กิวเมนต์ของ C เนื่องจาก A ไม่สามารถเข้าถึง B ได้ ด้วยวิธีนี้ C ยังคงเป็นส่วนตัวสำหรับ B เท่านั้น
ข้อขัดแย้งของชื่อเมื่ออาร์กิวเมนต์หรือตัวแปรสองตัวในขอบเขตของการปิดมีชื่อเหมือนกัน ความขัดแย้งของชื่อ (ความขัดแย้งของชื่อ- ซ้อนกันมากขึ้น ( ภายในมากขึ้น) ขอบเขตมีลำดับความสำคัญ ดังนั้นขอบเขตที่ซ้อนกันมากที่สุดจึงมีลำดับความสำคัญสูงสุด และในทางกลับกัน นี่คือขอบเขตของขอบเขต ( ห่วงโซ่ขอบเขต- ลิงก์แรกสุดคือขอบเขตที่ลึกที่สุด และในทางกลับกัน พิจารณาสิ่งต่อไปนี้:
ฟังก์ชั่นภายนอก() ( var x = 5; ฟังก์ชั่นภายใน(x) ( return x * 2; ) กลับภายใน; ) ภายนอก())(10); // คืนค่า 20 แทนที่จะเป็น 10
ความขัดแย้งของชื่อเกิดขึ้นในคำสั่ง return x * 2 ระหว่างพารามิเตอร์ x ของฟังก์ชันภายในและตัวแปร x ของฟังก์ชันภายนอก ห่วงโซ่ขอบเขตที่นี่จะเป็นดังนี้: ( inside ==> ภายนอก ==> global object ( วัตถุระดับโลก- ดังนั้น x ของฟังก์ชันภายในจะมีลำดับความสำคัญมากกว่าฟังก์ชันภายนอก และเราจะถูกส่งกลับ 20 (= 10 * 2) แทนที่จะเป็น 10 (= 5 * 2)
การปิด(ปิด)
การปิดเป็นหนึ่งในคุณสมบัติหลักของ JavaScript JavaScript อนุญาตให้มีการซ้อนฟังก์ชันและให้ฟังก์ชันที่ซ้อนกันเข้าถึงตัวแปรและฟังก์ชันทั้งหมดที่ประกาศไว้ภายในฟังก์ชันภายนอกได้อย่างเต็มที่ (และตัวแปรและฟังก์ชันอื่นๆ ที่ฟังก์ชันภายนอกสามารถเข้าถึงได้)
อย่างไรก็ตาม ฟังก์ชันภายนอกไม่สามารถเข้าถึงตัวแปรและฟังก์ชันที่ประกาศในฟังก์ชันภายในได้ นี่เป็นการห่อหุ้มตัวแปรภายในฟังก์ชันที่ซ้อนกัน
นอกจากนี้ เนื่องจากฟังก์ชันที่ซ้อนกันสามารถเข้าถึงขอบเขตของฟังก์ชันภายนอกได้ ตัวแปรและฟังก์ชันที่ประกาศในฟังก์ชันภายนอกจะยังคงมีอยู่ต่อไปหลังจากการดำเนินการสำหรับฟังก์ชันที่ซ้อนกัน หากเข้าถึงได้และยังคงรักษาไว้ (หมายความว่าตัวแปรที่ประกาศใน ฟังก์ชันฟังก์ชันภายนอกจะถูกเก็บไว้ก็ต่อเมื่อฟังก์ชันภายในเข้าถึงฟังก์ชันเหล่านั้น)
การปิดจะถูกสร้างขึ้นเมื่อฟังก์ชันที่ซ้อนกันสามารถเข้าถึงได้ในบางขอบเขตนอกฟังก์ชันภายนอก
Var pet = function(name) ( // ฟังก์ชันภายนอกประกาศตัวแปร "name" var getName = function() ( return name; // ฟังก์ชันที่ซ้อนกันสามารถเข้าถึง "name" ของฟังก์ชันภายนอก ) return getName; / / ส่งคืนฟังก์ชันที่ซ้อนกัน ดังนั้นจึงรักษาการเข้าถึง // ไปยังขอบเขตอื่น) myPet = pet("Vivie"); myPet(); // "Vivie" ถูกส่งคืน // เพราะ แม้หลังจากดำเนินการฟังก์ชันภายนอกแล้ว // ชื่อจะถูกเก็บรักษาไว้สำหรับฟังก์ชันที่ซ้อนกัน
ตัวอย่างที่ซับซ้อนยิ่งขึ้นแสดงไว้ด้านล่าง วัตถุที่มีวิธีการจัดการกับฟังก์ชันที่ซ้อนกันโดยฟังก์ชันภายนอกสามารถส่งคืนได้ ( กลับ).
Var createPet = function(name) ( var sex; return ( setName: function(newName) ( name = newName; ), getName: function() ( return name; ), getSex: function() ( return sex; ), setSex: ฟังก์ชั่น(newSex) ( if(typeof newSex === "string" && (newSex.toLowerCase() === "male" || newSex.toLowerCase() === "Female")) ( sex = newSex; ) ) ) ) var pet = createPet("Vivie"); pet.getName(); // Vivie pet.setName("โอลิเวอร์"); pet.setSex("ชาย"); สัตว์เลี้ยง.getSex(); // ตัวผู้ pet.getName(); //โอลิเวอร์
ในโค้ดด้านบน ตัวแปรชื่อของฟังก์ชันภายนอกสามารถเข้าถึงได้โดยฟังก์ชันที่ซ้อนกัน และไม่มีวิธีอื่นในการเข้าถึงตัวแปรที่ซ้อนกัน ยกเว้นผ่านฟังก์ชันที่ซ้อนกัน ตัวแปรที่ซ้อนกันของฟังก์ชันที่ซ้อนกันคือ สิ่งอำนวยความสะดวกการจัดเก็บที่ปลอดภัยสำหรับอาร์กิวเมนต์และตัวแปรภายนอก ประกอบด้วยข้อมูล "ถาวร" และ "ห่อหุ้ม" สำหรับฟังก์ชันที่ซ้อนกันเพื่อจัดการ ฟังก์ชันไม่จำเป็นต้องถูกกำหนดให้กับตัวแปรหรือมีชื่อด้วยซ้ำ
Var getCode = (function() ( var apiCode = "0]Eal(eh&2"; // โค้ดเราไม่ต้องการให้บุคคลภายนอกสามารถแก้ไขได้... return function() ( return apiCode; ); )()) ; getCode(); // ส่งคืน apiCode
อย่างไรก็ตาม มีข้อผิดพลาดหลายประการที่ต้องพิจารณาเมื่อใช้การปิด หากฟังก์ชันส่วนตัวกำหนดตัวแปรที่มีชื่อเดียวกันกับชื่อของตัวแปรในขอบเขตภายนอก จะไม่มีทางอ้างถึงตัวแปรในขอบเขตภายนอกได้อีก
Var createPet = function(name) ( // ฟังก์ชั่นภายนอกกำหนดตัวแปรชื่อ "name" return ( setName: function(name) ( // ฟังก์ชั่นที่แนบมายังกำหนดตัวแปรชื่อ "name" อีกด้วย name = name; // เราจะเข้าถึง "ชื่อ" ที่กำหนดโดยฟังก์ชันภายนอกได้อย่างไร
การใช้วัตถุอาร์กิวเมนต์วัตถุอาร์กิวเมนต์ของฟังก์ชันคืออาร์เรย์เทียม ภายในฟังก์ชัน คุณสามารถอ้างถึงข้อโต้แย้งดังนี้:
อาร์กิวเมนต์[i]
โดยที่ i คือเลขลำดับของอาร์กิวเมนต์ โดยเริ่มจาก 0 อาร์กิวเมนต์แรกที่ส่งไปยังฟังก์ชันจะระบุเป็นอาร์กิวเมนต์ และรับจำนวนอาร์กิวเมนต์ทั้งหมด - arguments.length
การใช้อ็อบเจ็กต์อาร์กิวเมนต์ คุณสามารถเรียกใช้ฟังก์ชันได้โดยส่งอาร์กิวเมนต์ไปให้ฟังก์ชันมากกว่าที่จะมีการประกาศอย่างเป็นทางการให้ยอมรับ สิ่งนี้มีประโยชน์มากหากคุณไม่รู้ว่าฟังก์ชันของคุณควรใช้อาร์กิวเมนต์จำนวนเท่าใด คุณสามารถใช้ arguments.length เพื่อกำหนดจำนวนอาร์กิวเมนต์ที่ส่งไปยังฟังก์ชัน จากนั้นเข้าถึงแต่ละอาร์กิวเมนต์โดยใช้ออบเจ็กต์อาร์กิวเมนต์
ตัวอย่างเช่น พิจารณาฟังก์ชันที่เชื่อมหลายสตริงเข้าด้วยกัน อาร์กิวเมนต์ที่เป็นทางการเพียงอย่างเดียวของฟังก์ชันคือสตริงที่ระบุอักขระที่แยกองค์ประกอบที่จะต่อกัน ฟังก์ชั่นถูกกำหนดดังนี้:
ฟังก์ชั่น myConcat(separator) ( var result = ""; var i; // วนซ้ำอาร์กิวเมนต์สำหรับ (i = 1; i< arguments.length; i++) { result += arguments[i] + separator; } return result; }
คุณสามารถส่งผ่านอาร์กิวเมนต์จำนวนเท่าใดก็ได้ไปยังฟังก์ชันนี้ และมันจะเชื่อมแต่ละอาร์กิวเมนต์ให้เป็นสตริงเดียว
// ส่งกลับ "แดง, ส้ม, น้ำเงิน, " myConcat(", ", "red", "orange", "blue"); // ส่งคืน "elephant; giraffe; lion; cheetah; " myConcat("; ", "elephant", "giraffe", "lion", "cheetah"); // ส่งคืน "sage.basil.oregano.pepper.parsley" myConcat(". ", "sage", "basil", "oregano", "pepper", "parsley");
เพราะ อาร์กิวเมนต์เป็นอาร์เรย์เทียม ซึ่งวิธีการอาร์เรย์บางวิธีจะนำไปใช้กับมัน เช่น สำหรับ .. in
ฟังก์ชั่น func() ( สำหรับ (ค่าในอาร์กิวเมนต์)( console.log(value); ) ) func(1, 2, 3); // 1 // 2 // 3
หมายเหตุ: อาร์กิวเมนต์เป็นอาร์เรย์หลอก แต่ไม่ใช่อาร์เรย์ นี่คืออาร์เรย์หลอกที่มีเลขดัชนีและคุณสมบัติความยาว อย่างไรก็ตาม ไม่มีวิธีการแบบอาร์เรย์ทั้งหมด
พารามิเตอร์ที่เหลือการใช้ฟังก์ชันลูกศรได้รับอิทธิพลจากปัจจัย 2 ประการ ได้แก่ ฟังก์ชันที่สั้นกว่าและศัพท์นี้
ฟังก์ชั่นที่สั้นกว่ารูปแบบการทำงานบางอย่างสนับสนุนการใช้ฟังก์ชันที่สั้นกว่า เปรียบเทียบ:
Var a = ["ไฮโดรเจน", "ฮีเลียม", "ลิเธียม", "เบริลเลียม" ]; var a2 = a.map(function(s) ( return s.length; )); console.log(a2); // บันทึก var a3 = a.map(s => s.length); console.log(a3); // บันทึก
คำศัพท์อันนี้ก่อนฟังก์ชันลูกศร แต่ละฟังก์ชันใหม่จะกำหนดค่าของตัวเอง (วัตถุใหม่ในกรณีของตัวสร้าง ไม่ได้กำหนดไว้ในโหมดเข้มงวด วัตถุบริบทหากฟังก์ชันถูกเรียกว่าเป็นวิธีการของวัตถุ ฯลฯ) สิ่งนี้กลายเป็นเรื่องน่ารำคาญจากมุมมองของรูปแบบการเขียนโปรแกรมเชิงวัตถุ
Function Person() ( // ตัวสร้าง Person() กำหนด `this` ด้วยตัวเอง this.age = 0; setInterval(function growUp() ( // หากไม่มีโหมดเข้มงวด ฟังก์ชัน growUp() จะกำหนด `this` // เป็น วัตถุโกลบอล ซึ่งแตกต่างจาก `this` // กำหนดโดยตัวสร้าง Person() this.age++; ) var p = new Person();
ECMAScript 3/5 แก้ไขปัญหานี้โดยการกำหนดค่าให้กับตัวแปรที่สามารถวนซ้ำได้
Function Person() ( var self = this; // บางคนเลือก `that` แทนที่จะเป็น `self` // เลือกอันหนึ่งแล้วทำให้สอดคล้องกัน self.age = 0; setInterval(function growUp() ( // การเรียกกลับไปยัง ตัวแปร `self` ซึ่ง // ค่าเป็นวัตถุที่คาดหวัง self.age++), 1,000);
ดูเพิ่มเติมที่ฟังก์ชันในการอ้างอิง JavaScript สำหรับข้อมูลเพิ่มเติมเกี่ยวกับฟังก์ชันเป็นอ็อบเจ็กต์