คำก่อนหน้านี้
ส่วนใหญ่แล้วเหตุผลหลักที่ทำให้เราสับสนเกี่ยวกับขอบเขตคือเราไม่สามารถแยกแยะว่าการค้นหาตัวแปรควรดำเนินการตามลำดับที่ซ้อนกันของตำแหน่งฟังก์ชันหรือตามลำดับของการเรียกใช้ฟังก์ชัน เมื่อรวมกับการรบกวนของกลไกนี้การค้นหาตัวแปรมีแนวโน้มที่จะเกิดข้อผิดพลาดมาก สิ่งนี้เกิดจากแบบจำลองการทำงานสองขอบเขต ขอบเขตแบ่งออกเป็นขอบเขตคำศัพท์และขอบเขตแบบไดนามิก ด้วยการแยกแยะโมเดลขอบเขตทั้งสองนี้คุณสามารถมีความเข้าใจที่ชัดเจนเกี่ยวกับกระบวนการค้นหาตัวแปร บทความนี้เป็นบทที่สองของชุดขอบเขต JavaScript - ขอบเขตคำศัพท์และขอบเขตไดนามิก
ขอบเขตคำศัพท์
ดังที่ได้กล่าวไว้ในบทความแรกขั้นตอนการทำงานแรกของคอมไพเลอร์เรียกว่าคำนามคำซึ่งสลายตัวสตริงที่ประกอบด้วยตัวละครเป็นหน่วยคำศัพท์ แนวคิดนี้เป็นพื้นฐานสำหรับการทำความเข้าใจขอบเขตคำศัพท์
พูดง่ายๆคือขอบเขตคำศัพท์กำหนดขอบเขตที่เวทีคำศัพท์ซึ่งถูกกำหนดโดยที่ตัวแปรและขอบเขตบล็อกถูกเขียนเมื่อเขียนโค้ด ดังนั้นขอบเขตยังคงไม่เปลี่ยนแปลงเมื่อเครื่องวิเคราะห์คำว่าประมวลผลรหัส
ความสัมพันธ์
ไม่ว่าจะเรียกฟังก์ชั่นที่ใดและไม่ว่าจะเรียกว่าขอบเขตคำศัพท์ของมันจะถูกกำหนดโดยตำแหน่งที่มีการประกาศฟังก์ชั่นเท่านั้น
ฟังก์ชั่น foo (a) {var b = a * 2; แถบฟังก์ชัน (c) {console.log (a, b, c);} bar (b * 3);} foo (2); // 2 4 12ในตัวอย่างนี้มีขอบเขตซ้อนกันสามขอบเขต เพื่อช่วยให้เข้าใจคิดว่าพวกเขาเป็นฟองสบู่หลายตัวที่รวมทีละขั้นตอน
ฟองสบู่จะถูกกำหนดโดยที่เขียนรหัสบล็อกขอบเขตที่สอดคล้องกันของพวกเขาและพวกเขาจะรวมอยู่ทีละขั้นตอน
Bubble 1 มีขอบเขตทั่วโลกทั้งหมดโดยมีตัวระบุเพียงตัวเดียวเท่านั้น: Foo
Bubble 2 มีขอบเขตที่สร้างโดย Foo ซึ่งมีตัวระบุสามตัว: A, Bar และ B
Bubble 3 มีขอบเขตที่สร้างโดย Bar โดยมีตัวระบุเพียงตัวเดียวเท่านั้น: C
หา
โครงสร้างของฟองสบู่ที่กำหนดขอบเขตและความสัมพันธ์ตำแหน่งของพวกเขาให้ข้อมูลตำแหน่งที่เพียงพอซึ่งเครื่องยนต์ใช้เพื่อค้นหาตำแหน่งของตัวระบุ
ในรหัสตัวอย่างของรหัสเครื่องยนต์ดำเนินการประชุม console.log (... ) และค้นหาการอ้างอิงถึงตัวแปรสามตัว A, B และ C มันเริ่มต้นด้วยขอบเขตด้านในสุดนั่นคือขอบเขตของฟังก์ชั่นบาร์ (... ) เครื่องยนต์ไม่สามารถหาได้ที่นี่ดังนั้นมันจะไปที่ระดับก่อนหน้าเพื่อค้นหาต่อไปในขอบเขตของ Foo ที่ซ้อนกัน (... ) พบได้ที่นี่ดังนั้นเครื่องยนต์จึงใช้ข้อมูลอ้างอิงนี้ เช่นเดียวกันสำหรับ b และสำหรับ C เครื่องยนต์พบในบาร์ (... )
[หมายเหตุ] การค้นหาขอบเขตคำศัพท์จะมองหาตัวระบุระดับแรกเท่านั้น หากรหัสอ้างอิง foo.bar.baz การค้นหาขอบเขตคำศัพท์จะพยายามค้นหาตัวระบุ FOO เท่านั้น หลังจากค้นหาตัวแปรนี้กฎการเข้าถึงแอตทริบิวต์วัตถุจะเข้ามาเข้าถึงแอตทริบิวต์ BAR และ BAZ ตามลำดับ
foo = {bar: {baz: 1}}; console.log (foo.bar.baz); // 1ปิดบัง
การค้นหาขอบเขตเริ่มต้นจากขอบเขตด้านในสุดที่อยู่ในตำแหน่งรันไทม์และดำเนินการทีละขั้นตอนออกไปข้างนอกหรือขึ้นไปจนกว่าจะพบตัวระบุการจับคู่ครั้งแรก
ตัวระบุที่มีชื่อเดียวกันสามารถกำหนดได้ในขอบเขตซ้อนหลายชั้นซึ่งเรียกว่า "เอฟเฟกต์การบดเคี้ยว" ตัวระบุภายใน "Occlude" ตัวระบุภายนอก
var a = 0; การทดสอบฟังก์ชั่น () {var a = 1; console.log (a); // 1} การทดสอบ ();ตัวแปรทั่วโลกเป็นแอตทริบิวต์ของวัตถุทั่วโลกโดยอัตโนมัติดังนั้นจึงสามารถเข้าถึงได้โดยตรงโดยอ้างอิงถึงแอตทริบิวต์ของวัตถุทั่วโลกแทนที่จะส่งผ่านชื่อคำศัพท์ของวัตถุทั่วโลกโดยตรง
var a = 0; การทดสอบฟังก์ชั่น () {var a = 1; console.log (window.a); // 0} ทดสอบ ();เทคนิคนี้ช่วยให้สามารถเข้าถึงตัวแปรส่วนกลางที่ถูกบดบังด้วยตัวแปรที่มีชื่อเดียวกัน แต่ถ้าตัวแปรที่ไม่ใช่ Global ถูกบล็อกพวกเขาไม่สามารถเข้าถึงได้ไม่ว่าจะเกิดอะไรขึ้น
ขอบเขตแบบไดนามิก
JavaScript ใช้ขอบเขตคำศัพท์และคุณสมบัติที่สำคัญที่สุดคือกระบวนการนิยามของมันเกิดขึ้นในระหว่างขั้นตอนการเขียนของรหัส
แล้วทำไมต้องแนะนำขอบเขตแบบไดนามิก? ในความเป็นจริงขอบเขตแบบไดนามิกเป็นอีกกลไกสำคัญของจาวาสคริปต์ต่อลูกพี่ลูกน้องนี้ ความสับสนส่วนใหญ่ของขอบเขตเป็นเพราะขอบเขตคำศัพท์และกลไกนี้สับสนดังนั้นฉันจึงไม่สามารถบอกความแตกต่างระหว่างความโง่เขลาได้
ขอบเขตแบบไดนามิกไม่สนใจว่าจะมีการประกาศฟังก์ชั่นและขอบเขตของขอบเขตอย่างไรและประกาศทุกที่เฉพาะที่พวกเขาถูกเรียกจาก กล่าวอีกนัยหนึ่งโซ่ขอบเขตจะขึ้นอยู่กับสแต็คการโทรไม่ใช่ขอบเขตการทำรังในรหัส
var a = 2; function foo () {console.log (a);} function bar () {var a = 3; foo ();} bar ();[1] หากอยู่ในขอบเขตคำศัพท์มันเป็นสภาพแวดล้อม JavaScript ปัจจุบัน ตัวแปร A ถูกค้นหาครั้งแรกในฟังก์ชั่น foo () แต่ไม่พบ ดังนั้นทำตามโซ่ขอบเขตเพื่อค้นหาในขอบเขตทั่วโลกค้นหาและกำหนดค่า 2 ดังนั้นคอนโซลเอาท์พุท 2
【 2 】หากอยู่ในขอบเขตแบบไดนามิกในทำนองเดียวกันตัวแปร A จะถูกค้นหาครั้งแรกใน foo () และไม่พบ ที่นี่คุณจะติดตามสแต็กการโทรเพื่อค้นหาในสถานที่ที่เรียกใช้ฟังก์ชัน foo () นั่นคือฟังก์ชัน bar () ค้นหาและกำหนดค่าให้ 3 ดังนั้นคอนโซลเอาต์พุต 3
สรุป: ความแตกต่างระหว่างสองขอบเขต ในระยะสั้นขอบเขตคำศัพท์จะถูกกำหนดในเวลานิยามในขณะที่ขอบเขตแบบไดนามิกจะถูกกำหนดในเวลาทำงาน
ด้านบนเป็นส่วนที่สองของขอบเขตคำศัพท์และขอบเขตแบบไดนามิกที่แนะนำโดยตัวแก้ไขให้คุณ ฉันหวังว่ามันจะเป็นประโยชน์กับคุณ หากคุณต้องการทราบข้อมูลเพิ่มเติมโปรดใส่ใจกับ wulin.com!