บทความนี้อธิบายในรายละเอียดวิธีการนิยามฟังก์ชั่นทั่วไปที่หลากหลายใน JavaScript และแบ่งปันกับคุณสำหรับการอ้างอิงของคุณ การวิเคราะห์เฉพาะมีดังนี้:
ก่อนอื่นมาดูคำจำกัดความของฟังก์ชั่นที่พบบ่อยที่สุดใน JavaScript:
ฟังก์ชั่นที่กำหนดด้วยตัวสร้างฟังก์ชันรหัสมีดังนี้:
var multiply = new function ('x', 'y', 'return x * y;');การประกาศฟังก์ชั่นวิธีนี้เป็นเรื่องธรรมดาที่สุด:
ฟังก์ชั่นคูณ (x, y) {return x * y;}การแสดงออกของฟังก์ชั่นที่ประกาศว่าเป็นฟังก์ชันที่ไม่ระบุชื่อและจากนั้นกำหนดให้กับตัวแปรเป็นวิธีการทั่วไป:
var multiply = function (x, y) {return x * y;}ฟังก์ชั่นนิพจน์ แต่การประกาศฟังก์ชั่นเป็นฟังก์ชันที่มีชื่อแล้วกำหนดค่าให้กับตัวแปรซึ่งดูเหมือนวิธีเดียวกัน:
var multiply = function multi (x, y) {return x * y;}ก่อนอื่นให้เปรียบเทียบชื่อฟังก์ชั่นและความสัมพันธ์โดยตรงระหว่างตัวแปรฟังก์ชันที่กำหนดให้กับฟังก์ชั่น มันเป็นเรื่องเล็กน้อย ... ที่จะใช้งานง่ายมากขึ้นจากตัวอย่างที่ 4 ตอนนี้มันเป็นความสัมพันธ์ระหว่างตัวแปรฟังก์ชันคูณและชื่อฟังก์ชั่น Multi:
ชื่อฟังก์ชั่นไม่สามารถแก้ไขได้ในทางตรงกันข้ามตัวแปรฟังก์ชันสามารถกำหนดใหม่ได้ ควรเข้าใจง่ายว่าตัวแปรฟังก์ชันสามารถกำหนดใหม่ได้ ในตัวอย่างที่สี่ของเราตัวแปรทวีคูณที่กำหนดไว้มันไม่น่าดูและกำหนดใหม่ให้:
multiply = function (x, y) {return x + y;}ฉันเปลี่ยนตัวเองทันทีจากการคูณเป็นเพิ่มเติม อย่างไรก็ตามมันเป็นไปไม่ได้ที่จะเปลี่ยนตัวแปรหลายฟังก์ชัน คำจำกัดความของฟังก์ชั่นมีอยู่แล้ว ตราบใดที่มันยังคงอ้างอิงมันจะไม่เปลี่ยนแปลง อาจไม่เข้าใจง่ายที่นี่ ลองคิดแบบนี้ก่อนแล้วมองลงไปและคุณควรจะเข้าใจมันช้า
ไม่สามารถใช้ชื่อฟังก์ชั่นนอกฟังก์ชั่นได้ในเวลาเดียวกันมันจะมองเห็นได้เฉพาะในตัวฟังก์ชั่น ตัวอย่างที่ง่ายมาก:
var foo = bar function () {alert ('hello');} foo (); // พรอมต์ "สวัสดี" แถบสตริง (); // ดำเนินการข้อผิดพลาดแถบไม่ได้กำหนดไว้และเห็นได้ชัดว่าแถบที่นี่เป็นชื่อฟังก์ชั่น แต่ไม่สามารถเรียกได้ว่าภายนอก ในเวลานี้จะมีรองเท้าเด็ก ๆ อย่างแน่นอนถามว่าทำไมตัวอย่างนี้ยังดูดีเช่นตัวอย่างที่ 4 ทำไมไม่ใช้วิธีการตัวอย่าง 2? คำถามที่ดีให้ฉันทำลายมันลงอย่างช้าๆ
ดำเนินการต่อด้วยตัวอย่างที่ 4 เราจะเห็นได้ว่าชื่อฟังก์ชัน (Multi) และตัวแปรฟังก์ชัน (ทวีคูณ) ไม่เหมือนกัน แต่ในความเป็นจริงทั้งสองไม่มีความสัมพันธ์เลยดังนั้นจึงไม่จำเป็นต้องรักษาความสอดคล้อง เมื่อพูดถึงสิ่งนี้ฉันคิดว่าตัวอย่างสี่ตัวอย่างข้างต้นควรลดลงเป็น 3 และตัวอย่างที่ 2 และตัวอย่าง 4 ควรสอดคล้องกันเป็นหลัก อะไรไม่เชื่อ? ฮิฮิฉันต้องรักษามันไว้ในความเงียบ ~ อ่านต่อไป ~~
เราพบว่าเมื่อเทียบกับตัวอย่างที่ 2 และตัวอย่างที่ 4 มีตัวแปรฟังก์ชัน VAR น้อยกว่าเท่านั้นในขณะที่เทียบกับตัวอย่างที่ 3 มีชื่อฟังก์ชันน้อยกว่าเท่านั้น จากมุมมองของปรากฏการณ์สาระสำคัญของตัวอย่างที่ 2 และตัวอย่าง 4 นั้นเหมือนกันและหลักฐานมีดังนี้:
ฟังก์ชั่น foo () {} Alert (foo); // แจ้งชื่อฟังก์ชั่นที่มี "foo" var bar = foo; Alert (bar); // แจ้งชื่อฟังก์ชั่นยังคงมี "foo" เท่านั้นและไม่มีความสัมพันธ์กับบาร์มันเป็น ironclad จริงหรือ? มันเป็นวิธีที่จะเขียนโค้ดข้างต้นคล้ายกับตัวอย่างที่ 2 ร่วมกับรหัสในตัวอย่างที่ 4 หรือไม่? ถูกต้องนี่คือสิ่งที่ฉันเพิ่งพูดว่าทั้งสองควรจะเหมือนกัน อย่างไรก็ตามเมื่อกำหนดฟังก์ชั่นในกรณีที่ 2 เครื่องยนต์ JS ช่วยให้เราทำอะไรบางอย่างเช่นการประกาศฟังก์ชั่นที่มีชื่อฟังก์ชั่นทวีคูณและการกำหนดตัวแปรอย่างเงียบ ๆ ที่เรียกว่าทวีคูณแล้วกำหนดให้กับตัวแปรนี้สองชื่อเดียวกัน เราคิดว่าเมื่อใช้ชื่อฟังก์ชั่นทวีคูณเราใช้ตัวแปรฟังก์ชั่นทวีคูณดังนั้นเราจึงเวียนหัว ~ เพื่อความซื่อสัตย์ฉันก็เวียนหัว ~ ในระยะสั้นเมื่อเราโทรมาเราเรียกตัวแปรฟังก์ชั่นจริง ๆ และชื่อฟังก์ชันไม่สามารถเรียกฟังก์ชั่นภายนอกได้
อย่างไรก็ตามความแตกต่างเล็กน้อยที่จะกล่าวถึงในที่นี้คือฟังก์ชั่นที่กำหนดโดยวิธีการประกาศฟังก์ชันนั้นแตกต่างจากการประกาศตัวสร้างหรือการประกาศการแสดงออกของฟังก์ชันวิธีการประกาศฟังก์ชันสามารถเรียกได้ก่อนคำจำกัดความของฟังก์ชั่น ...
foo (); // เคล็ดลับ foofunction foo () {แจ้งเตือน ('foo');} bar (); // บัดดี้มันแตกต่างจากด้านบนจริงๆดังนั้นอย่าอวด นี่ไม่ใช่ความผิดพลาดหรือไม่? แถบพรอมต์ไม่ได้กำหนด var bar = function () {alert ('bar');}มาพูดคุยเกี่ยวกับฟังก์ชั่นที่ประกาศโดยตัวสร้าง ฟังก์ชั่นที่ประกาศจะไม่สืบทอดขอบเขตของตำแหน่งที่ประกาศในปัจจุบัน พวกเขาจะมีขอบเขตทั่วโลกโดยค่าเริ่มต้นเท่านั้น อย่างไรก็ตามนี่เป็นสิ่งเดียวกันในวิธีการประกาศฟังก์ชั่นอื่น ๆ ดังนี้:
function foo () {var hi = 'hello'; // return function () {// Alert (hi); - ฟังก์ชั่น return ('return hi;');} foo () (); // สำหรับเอฟเฟกต์การดำเนินการโปรดเรียกใช้และดูด้วยตัวเองมันสามารถจินตนาการได้ว่าการดำเนินการของฟังก์ชั่นที่ส่งคืนโดยการใช้ประกาศตัวสร้างจะรายงานข้อผิดพลาดอย่างหลีกเลี่ยงไม่ได้เนื่องจากตัวแปร HI ไม่ได้อยู่ในขอบเขต (เช่นขอบเขตทั่วโลก)
อีกประเด็นหนึ่งคือผู้คนมักจะพูดว่าฟังก์ชั่นที่ประกาศในโหมดคอนสตรัคเตอร์นั้นไม่มีประสิทธิภาพ ทำไมถึงเป็นเช่นนี้? วันนี้ฉันเรียนรู้จากเอกสารที่ฟังก์ชั่นที่ประกาศในอีกสามวิธีจะถูกแยกวิเคราะห์เพียงครั้งเดียว ในความเป็นจริงพวกเขามีอยู่ในการปิด แต่นั่นเกี่ยวข้องกับห่วงโซ่ขอบเขตเท่านั้นและร่างกายฟังก์ชั่นจะถูกแยกวิเคราะห์เพียงครั้งเดียว แต่วิธีการสร้างคือทุกครั้งที่มีการดำเนินการฟังก์ชั่นร่างกายฟังก์ชั่นของมันจะถูกแยกวิเคราะห์หนึ่งครั้ง เราสามารถคิดได้ว่าฟังก์ชั่นที่ประกาศด้วยวิธีนี้เป็นวัตถุซึ่งเก็บพารามิเตอร์และตัวถังฟังก์ชั่น ทุกครั้งที่มีการดำเนินการมันจะต้องแยกวิเคราะห์หนึ่งครั้งและพารามิเตอร์และร่างกายฟังก์ชั่นจะถูกดำเนินการซึ่งย่อมจะไม่มีประสิทธิภาพ ไม่ทราบวิธีการทดลองเฉพาะหรือไม่?
สุดท้ายเรามาพูดถึงสิ่งที่ไม่มีใครให้ความสนใจ เมื่อใดที่ดูเหมือนว่าวิธีการประกาศฟังก์ชั่นไม่ใช่วิถีชีวิตของการทำงาน (มันยังคงมีแนวโน้มที่จะนำไปใช้อย่างง่าย ๆ เมื่อวิธีการของตัวอย่างที่ 2 กลายเป็นอีกวิธีหนึ่งโดยไม่ตั้งใจ):
เมื่อมันกลายเป็นส่วนหนึ่งของนิพจน์มันเป็นเหมือนตัวอย่างที่ 3 และตัวอย่าง 4
มันไม่ได้เป็น "องค์ประกอบต้นทาง" ของสคริปต์หรือฟังก์ชั่นอีกต่อไป องค์ประกอบต้นทางคืออะไร? นั่นคือข้อความที่ไม่ได้ถูกทอดทิ้งในสคริปต์หรือร่างกายฟังก์ชั่นเช่น:
var x = 0; // องค์ประกอบที่มาถ้า (x == 0) {// องค์ประกอบแหล่งที่มา x = 10; // ไม่ใช่องค์ประกอบของแหล่งที่มาเนื่องจากมันซ้อนกันในฟังก์ชันคำสั่ง if boo () {} // ไม่ใช่องค์ประกอบของแหล่งที่มาเพราะมันซ้อนกันในฟังก์ชัน IF คำสั่ง} foo () {// องค์ประกอบที่มา var y = 20; // แถบฟังก์ชันองค์ประกอบต้นทาง () {} // องค์ประกอบที่มาในขณะที่ (y == 10) {// ฟังก์ชันองค์ประกอบแหล่งที่มา blah () {} // ไม่ใช่องค์ประกอบแหล่งที่มาเพราะมันซ้อนกันในคำสั่งขณะอยู่ y ++; // ไม่ใช่องค์ประกอบแหล่งที่มาเพราะมันซ้อนกันในคำสั่งขณะที่}}}ฉันเข้าใจแนวคิดขององค์ประกอบแหล่งที่มาอย่างคร่าวๆ ฉันจะดำเนินการต่อด้วยการประกาศฟังก์ชั่นที่ฉันเพิ่งพูดถึง โปรดดู:
// ฟังก์ชั่นฟังก์ชั่นฟังก์ชั่น foo () {} // ฟังก์ชันนิพจน์ (ฟังก์ชั่นแถบ () {}) // ฟังก์ชั่นนิพจน์ x = ฟังก์ชั่นสวัสดี () {} ถ้า (x) {// ฟังก์ชั่นฟังก์ชั่นฟังก์ชั่นโลก () {}} // ฟังก์ชั่นฟังก์ชัน A () {// ฟังก์ชั่นฟังก์ชันฟังก์ชันสุดท้ายให้ฉันพูดถึงความเข้าใจของตัวเอง เหตุผลในการแยกแยะระหว่างการประกาศฟังก์ชั่นและการประกาศที่ไม่ใช่ฟังก์ชันคือในมุมมองของฉันคำจำกัดความฟังก์ชันของวิธีการประกาศฟังก์ชั่นจะถูกประกาศล่วงหน้าเมื่อเครื่องยนต์ JS แยกวิเคราะห์ JS ดำเนินการ นั่นคืออย่างที่เราเพิ่งกล่าวไว้ข้างต้นมันสามารถใช้ก่อนนิยามฟังก์ชั่น อันที่จริงแล้วเครื่องยนต์วิเคราะห์ได้แยกวิเคราะห์ก่อนที่เราจะใช้มัน อย่างไรก็ตามการประกาศแบบไม่ใช้ฟังก์ชันเช่นการประกาศฟังก์ชั่นการแสดงออกเครื่องยนต์การแยกวิเคราะห์ JS จะกำหนดตัวแปรที่ประกาศโดย VAR ล่วงหน้าเท่านั้น ในเวลานี้ค่าตัวแปรจะไม่ได้กำหนดและการกำหนดจริงให้กับตัวแปรนี้อยู่ในตำแหน่งจริงของรหัส ดังนั้นข้อผิดพลาดดังกล่าวข้างต้นจึงไม่ได้กำหนดไว้ทั้งหมด ตัวแปรจริงได้รับการกำหนด แต่ยังไม่ได้รับมอบหมาย เอ็นจิ้นการแยกวิเคราะห์ JS ไม่ทราบว่ามันเป็นฟังก์ชั่น
ฉันเชื่อว่าคำอธิบายในบทความนี้มีค่าอ้างอิงบางอย่างสำหรับการออกแบบการเขียนโปรแกรมเว็บ JavaScript ของทุกคน