การทำงาน
รูปแบบฟังก์ชัน
ฟังก์ชั่น getPrototynames (o,/*เป็นตัวเลือก*/ a) {a = a || []; สำหรับ (var p ใน o) {a.push (p);} return a;}ผู้โทรหา
func.caller ส่งคืนฟังก์ชั่นผู้โทร
ฟังก์ชั่น callfunc () {ถ้า (callfunc.caller) {แจ้งเตือน (callfunc.caller.toString ());} else {แจ้งเตือน ("ไม่มีฟังก์ชั่นเรียก");}} ฟังก์ชัน handleCaller () {callfunc ();คนเจ้าชู้
วิธีที่ไม่ระบุชื่อเรียกใช้ซ้ำ
การแจ้งเตือน ((ฟังก์ชั่น (x) {ถ้า (x <=) return; return x * arguments.callee (x -);} ())); //ขอบเขต
ทุกคนคุ้นเคยกับขอบเขต วันนี้ฉันจะพูดถึงปัญหาการปิดและเข้าใจปัญหาการปิดอย่างละเอียด
<script> var global = "global scope"; // นี่คือขอบเขตฟังก์ชันขอบเขตส่วนกลาง () {var scope = "ขอบเขตท้องถิ่น"; // นี่คือขอบเขตการส่งคืนขอบเขตท้องถิ่น; // ขอบเขตที่ส่งคืนเป็นตัวแปรท้องถิ่น} </script>1.: ตัวแปรทั่วโลกที่กำหนดยังสามารถเข้าถึงได้ภายในฟังก์ชั่น เมื่อตัวแปรท้องถิ่นที่กำหนดและชื่อตัวแปรส่วนกลางเหมือนกันตัวแปรท้องถิ่นจะซ่อนตัวแปรส่วนกลางและจะไม่ทำลายค่าของตัวแปรทั่วโลก
var scope = "Global Scope"; function f () {var scope = "Local Scope"; Return Scope;} Alert (f ()); // scopealert ท้องถิ่น (ขอบเขต); // ขอบเขตทั่วโลก;ข้างต้นเป็นเรื่องง่ายที่จะเข้าใจใช่ไหม?
2. ตัวแปรทั่วโลกสามารถประกาศได้โดยไม่ต้อง VAR แต่ตัวแปรท้องถิ่นจะต้องประกาศด้วย VAR หากตัวแปรท้องถิ่นไม่ใช้การประกาศ VAR คอมไพเลอร์จะเริ่มต้นเป็นตัวแปรส่วนกลาง
<span style = "line-height: .; font-family: verdana, arial, helvetica, sans-serif; font-size: px; พื้นหลัง-สี: rgb (,,);"> </span> ขอบเขต = "ขอบเขตทั่วโลก"; ฟังก์ชัน f ()
อย่างไรก็ตามตัวแปรทั่วโลกไม่ได้ใช้การประกาศ VAR และมีให้เฉพาะสำหรับโหมดที่ไม่ใช่ Strict หากใช้โหมดที่เข้มงวดจะมีการรายงานข้อผิดพลาด
<script> "ใช้อย่างเข้มงวด"; scope = "Global Scope"; function f () {scope = "Local Scope"; Return Scope;} Alert (f ()); // scopealert ท้องถิ่น (ขอบเขต); // ขอบเขตท้องถิ่น </script>ดังนั้นขอแนะนำให้คุณไม่ละเว้น var เมื่อประกาศตัวแปรเนื่องจากสามารถหลีกเลี่ยงปัญหาที่ไม่จำเป็น
3. ไม่เป็นไรที่จะประกาศล่วงหน้า อะไรคือสิ่งที่ล่วงหน้าของเวลา
<script> "ใช้อย่างเข้มงวด"; ขอบเขต; console.log (ขอบเขต); var scope = "Global Scope"; console.log (ขอบเขต); </script>
สิ่งนี้อาจถูกมองว่าเป็นคนแรกที่พิมพ์ไม่ได้กำหนด ใช่มันยังไม่ได้รับการกำหนดค่า การมอบหมายต่อไปนี้สามารถกำหนดขอบเขตทั่วโลก
นี่ไม่ผิด แต่ทำไมสิ่งนี้ถึงเกิดขึ้น? ไม่ควรกำหนดตัวแปรก่อนที่จะใช้งานได้หรือไม่?
ที่นี่ฉันจะบอกคุณเกี่ยวกับห่วงโซ่ขอบเขต JavaScript เป็นภาษาที่มีขอบเขตคำศัพท์
1. โซ่ขอบเขตเป็นวัตถุหรือรายการที่เชื่อมโยง ชุดรหัสนี้กำหนดตัวแปร "ในขอบเขต" ของรหัสนี้ เมื่อ JavaScript ต้องการค้นหาขอบเขตตัวแปรมันจะพัฒนาและค้นหาจากวัตถุแรกในห่วงโซ่ หากวัตถุแรกคือขอบเขตค่าของวัตถุนี้จะถูกส่งคืนโดยตรง หากไม่มีอยู่มันจะยังคงค้นหาวัตถุที่สองต่อไปจนกว่าจะพบ หากไม่พบตัวแปรในห่วงโซ่ขอบเขตข้อผิดพลาดจะถูกโยนลงไป
เราสามารถแสดงห่วงโซ่ฟังก์ชั่นนี้ได้ดังนี้: ค้นหาขอบเขต-> หน้าต่าง (วัตถุทั่วโลก) จากนั้นกำหนดขอบเขต อย่างไรก็ตามการดำเนินการที่ได้รับมอบหมายไม่ได้ดำเนินการและการดำเนินการที่ได้รับมอบหมายดำเนินการในภายหลังดังนั้นค่าจะไม่ได้กำหนดในเวลานี้
4. นี่เป็นความสับสนมากขึ้น ค่าที่พิมพ์คืออะไร?
<script> "ใช้อย่างเข้มงวด"; var scope = "Global Scope"; function f () {console.log (ขอบเขต); var scope = "ขอบเขตท้องถิ่น"; console.log (ขอบเขต);} f (); </script>ดูรหัสนี้: หากคุณประมาทคุณอาจเขียนคำตอบที่ผิด:
1. ขอบเขต gobal
2. ขอบเขตท้องถิ่น
การวิเคราะห์: ประกาศตัวแปรทั่วโลก เมื่ออยู่ในร่างกายฟังก์ชั่นตัวแรกแสดงถึงตัวแปรระดับโลกดังนั้น Global จะถูกพิมพ์และอันที่สองจะกำหนดตัวแปรท้องถิ่นครอบคลุมขอบเขตทั่วโลกดังนั้นขอบเขตท้องถิ่นจะถูกพิมพ์
การวิเคราะห์ดังกล่าวถูกต้องอย่างสมบูรณ์ใน C# Java แต่การวิเคราะห์ที่นี่ผิดแน่นอน
สิ่งนี้แสดงให้เห็นว่าก่อนปัญหานี้มาดูคำถามก่อน
ประโยคนี้มีความสำคัญมาก: ตัวแปรทั่วโลกจะถูกกำหนดไว้ในโปรแกรมเสมอ ตัวแปรท้องถิ่นมักจะถูกกำหนดไว้ในร่างกายของฟังก์ชั่นที่ประกาศและฟังก์ชั่นที่ทำรัง
หากคุณกำลังทำงานเป็นภาษาระดับสูงคุณจะได้รับการสัมผัสกับ JavaScript ไม่เหมาะสมเล็กน้อยสำหรับคำจำกัดความขอบเขต ฉันเหมือนกัน ลองมาดูตัวอย่าง:
<script> var g = "global scope"; function f () {สำหรับ (var i =; i <; i ++) {สำหรับ (var j =; j <; j ++) {;} console.log (j);} console.log (i);} console.log (g); f ();ผลของการพิมพ์คืออะไร?
คุณจะเห็นว่า {} หมายถึงบล็อกคำสั่งและบล็อกคำสั่งอยู่ในขอบเขตของบล็อกเดียวกันดังนั้นคุณอาจเดาได้ว่าค่า J และ I ได้รับการปล่อยตัวในหน่วยความจำดังนั้นผลลัพธ์จะต้องไม่ได้กำหนด
ผลลัพธ์ที่แท้จริงอาจทำให้คุณผิดหวัง
ทำไมสิ่งนี้ถึงเกิดขึ้น? การแสดงออกของฉันเริ่มต้นเหมือนคุณ
ตรวจสอบประโยคที่ฉันขอให้คุณจำตอนนี้ - - ตัวแปรทั่วโลกจะถูกกำหนดไว้ในโปรแกรมเสมอ ตัวแปรท้องถิ่นมักจะถูกกำหนดไว้ในร่างกายของฟังก์ชั่นที่ประกาศและฟังก์ชั่นที่ทำรัง
เพื่อความแม่นยำพารามิเตอร์ของฟังก์ชั่นยังอยู่ในหมวดหมู่ของตัวแปรท้องถิ่น ประโยคนี้ก็สำคัญมาก! - -
ประโยคนั้นประมาณว่าตราบใดที่ตัวแปรที่กำหนดไว้ในฟังก์ชั่นนั้นใช้ได้ภายในฟังก์ชั่นทั้งหมด ดังนั้นผลลัพธ์จึงไม่ยากที่จะเข้าใจ มองย้อนกลับไปที่คำถามของเราคุณเข้าใจไหม?
ห่วงโซ่ของการกระทำยังมีคำจำกัดความต่อไปนี้:
1. ห่วงโซ่การกระทำประกอบด้วยวัตถุระดับโลก
2. ในร่างกายฟังก์ชั่นที่ไม่มีการทำรังมีวัตถุสองชิ้นในห่วงโซ่การกระทำ วัตถุแรกกำหนดพารามิเตอร์ฟังก์ชั่นและตัวแปรท้องถิ่นและที่สองคือวัตถุทั่วโลก
3. ในร่างกายฟังก์ชั่นซ้อนกันมีวัตถุอย่างน้อยสามชิ้นในห่วงโซ่การกระทำ
เมื่อมีการกำหนดฟังก์ชั่นจะมีการบันทึกห่วงโซ่ขอบเขต
เมื่อฟังก์ชั่นนี้เรียกว่ามันจะสร้างวัตถุใหม่เพื่อจัดเก็บตัวแปรท้องถิ่นและเพิ่มวัตถุนี้ในห่วงโซ่การกระทำที่บันทึกไว้ ในเวลาเดียวกันสร้างห่วงโซ่ใหม่ของฟังก์ชั่นที่แสดงถึงการเรียกใช้ฟังก์ชั่น
สำหรับฟังก์ชั่นที่ซ้อนกันเมื่อมีการเรียกฟังก์ชั่นภายนอกฟังก์ชั่นภายในจะถูกกำหนดใหม่อีกครั้ง เนื่องจากทุกครั้งที่มีการเรียกฟังก์ชั่นภายนอกห่วงโซ่การกระทำจึงแตกต่างกัน ฟังก์ชั่นภายในมีความแตกต่างเล็กน้อยทุกครั้งที่กำหนดไว้ ทุกครั้งที่มีการเรียกฟังก์ชันภายนอกรหัสของฟังก์ชั่นภายในจะเหมือนกันและขอบเขตของรหัสที่เกี่ยวข้องก็แตกต่างกันเช่นกัน
การปิด
หลังจากทำมานานแล้วในที่สุดฉันก็ต้องพูดถึงเรื่องนี้ แต่มาวิเคราะห์ขอบเขตมาก่อน
<script> var nameg = "global" var g = function f () {console.log (ชื่อ); ฟังก์ชัน demo () {console.log ("demo =" + ชื่อ);} var name = ""; ฟังก์ชัน demo () {name = "" console.log ("demo =" + ชื่อ) nameg);} demo (); demo (); demo ();}; g (); </script>เราวิเคราะห์ตามห่วงโซ่แอ็คชั่น:
โทร demo0, demo0 () -> ค้นหาชื่อไม่พบ -> f (), return
โทร Demo1, demo1 ()-> ค้นหาชื่อ, ค้นหา, return
โทร demo2, demo2 () -> ค้นหา nameg, ไม่พบ -> f () เพื่อค้นหา nameg, ไม่พบ -> หน้าต่างเพื่อค้นหา nameg, return
ดูตัวอย่างนี้:
<script> ฟังก์ชั่น f () {var count =; return {counter: function () {return count ++;}, รีเซ็ต: function () {return count =;}}} var d = f (); var c = f (); console.log ("การโทรครั้งแรก:" "+ C.Counter ()); // </script>อย่างที่คุณเห็นในตัวอย่างนี้ฉันทำการนับและการดำเนินการเป็นศูนย์
อินสแตนซ์วัตถุสองรายการถูกสร้างขึ้นแต่ละรายการมีโซ่ขอบเขตของตัวเองดังนั้นค่าของพวกเขาจะไม่ส่งผลต่อกันและกัน เมื่อ C ถูกเรียกว่าเป็นครั้งที่สองค่าการนับจะถูกบันทึกเนื่องจากวัตถุ C ไม่ถูกทำลาย หลังจากเข้าใจตัวอย่างนี้ตัวอย่างต่อไปนี้จะเข้าใจได้ง่ายขึ้น
ทุกคนควรชัดเจนเกี่ยวกับกระบวนการนี้ ดังนั้นตอนนี้มาดูปัญหาการปิด ฉันตั้งปุ่มสี่ปุ่มและคลิกแต่ละปุ่มเพื่อส่งคืนชื่อการตอบกลับ
<body> <script> ฟังก์ชั่น btninit () {สำหรับ (var i =; i <; i ++) {var btn = document.getElementById ("btn" + i); btn.addeventListener ("คลิก", function () {alert ("btn" + i); id = "btn"> btn </button> <button id = "btn"> btn </button> <button id = "btn"> btn </button> <button id = "btn"> btn </button> </div> </body>คลิกเพื่อเรียกใช้ แต่ผลลัพธ์คือ BTN5 ทั้งหมด;
เรานั่งลงกับการวิเคราะห์ตอนนี้ ก่อนอื่นเราต้องเรียกฟังก์ชันที่ไม่ระบุชื่อ -> ค้นหาฉันไม่พบ -> btninit () และพบว่าฉันอยู่ในวง เปิดขึ้น เรารู้ว่ามีเพียงการเปิดตัวฟังก์ชั่นเท่านั้นที่ปล่อยออกมาและ I In For นั้นสามารถมองเห็นได้เสมอดังนั้นค่าสุดท้ายที่ฉันจะถูกเก็บไว้ ดังนั้นจะแก้ปัญหาได้อย่างไร
เพื่อแก้ปัญหาที่ค่า I ไม่สามารถมองเห็นได้เสมอในฟังก์ชั่นเราจำเป็นต้องใช้การทำรังของฟังก์ชั่นและส่งผ่านค่า I
ฟังก์ชั่น btninit () {สำหรับ (var i =; i <; i ++) {(ฟังก์ชั่น (data_i) {var btn = document.getElementById ("btn" + data_i); btn.addeventListener ("คลิก"ดูที่รหัสที่แก้ไขก่อนอื่นให้ดำเนินการครั้งแรกและสร้างวัตถุ ก่อนอื่นเราเรียกใช้ฟังก์ชันที่ไม่ระบุชื่อ -> data_i แต่ไม่พบ -> ฟังก์ชั่น (data_i) จากนั้นดำเนินการอีกครั้งเพื่อสร้างวัตถุ กฎการปิดบอกว่าพวกเขาไม่ส่งผลกระทบต่อกันและกัน ดังนั้นผลลัพธ์ที่ถูกต้องสามารถรับได้
ด้านบนเป็นฟังก์ชั่น JavaScript ต้องรู้ (9) ฟังก์ชั่นที่ตัวแก้ไขแนะนำให้คุณ เมื่อพูดถึงความรู้ที่เกี่ยวข้องเกี่ยวกับปัญหาการปิดฉันหวังว่ามันจะเป็นประโยชน์กับคุณ หากคุณมีคำถามใด ๆ โปรดฝากข้อความถึงฉันและบรรณาธิการจะตอบกลับคุณทันเวลา ขอบคุณมากสำหรับการสนับสนุนเว็บไซต์ Wulin.com!