วิธีเริ่มต้นใช้งาน VUE3.0 อย่างรวดเร็ว: เข้าสู่การเรียนรู้
คำแนะนำที่เกี่ยวข้อง: บทช่วยสอน JavaScript
เรามักจะได้ยิน "สภาพแวดล้อมการดำเนินการ", "ขอบเขต", "ต้นแบบ (ลูกโซ่)", "บริบทการดำเนินการ" ฯลฯ สิ่งเหล่านี้อธิบายอะไร
เรารู้ว่า js เป็นภาษาที่พิมพ์ได้ไม่ชัดเจน และประเภทของตัวแปรจะถูกกำหนดเฉพาะที่รันไทม์เท่านั้น เมื่อเอ็นจิ้น js รันโค้ด js มันก็จะทำการ วิเคราะห์คำศัพท์ การวิเคราะห์ไวยากรณ์ การวิเคราะห์ เชิงความหมาย และการประมวลผลอื่นๆ จากบนลงล่าง และสร้าง AST (แผนผังไวยากรณ์นามธรรม) หลังจากการวิเคราะห์โค้ดเสร็จสิ้น และสุดท้ายก็สร้างโค้ดเครื่อง ที่ CPU สามารถดำเนินการตาม AST และดำเนินการได้
นอกจากนี้ กลไก JS จะดำเนินการประมวลผลอื่น ๆ เมื่อเรียกใช้โค้ด ตัวอย่างเช่น มีสองขั้นตอนใน V8:
สิ่งนี้นำไปสู่ สองแนวคิด: "บริบทการดำเนินการ" และ "ห่วงโซ่ขอบเขต"
จากที่กล่าวมาข้างต้น เราสามารถทราบได้ว่า เมื่อโค้ด js ดำเนินการกับโค้ดที่ปฏิบัติการได้ บริบทการดำเนินการที่เกี่ยวข้องจะถูกสร้างขึ้น
ก่อนอื่น มีแนวคิดที่สอดคล้องกับโค้ดปฏิบัติการใน js: "สภาพแวดล้อมการดำเนินการ" - สภาพแวดล้อมโกลบอล สภาพแวดล้อมการทำงาน และ eval
ประการที่สอง สำหรับแต่ละบริบทการดำเนินการ มีคุณลักษณะที่สำคัญสามประการ:
มาดูโค้ดสองชิ้นกัน:
var scope="global scope"; var scope="ขอบเขตท้องถิ่น"; ฟังก์ชัน ฉ(){ ขอบเขตการส่งคืน; - กลับ f();}checkscope();
var scope="global scope";function checkscope(){ var scope="ขอบเขตท้องถิ่น"; ฟังก์ชัน ฉ(){ ขอบเขตการส่งคืน; - return f;}checkscope()();
พวกเขาจะพิมพ์อะไร?
ทำไม คำตอบก็คือสแต็กบริบทการดำเนินการแตกต่างกัน!
"สแต็กบริบทการดำเนินการ" คืออะไร
เมื่อดำเนินการโค้ดที่ปฏิบัติการได้ จะมีการเตรียมการล่วงหน้า "การเตรียมการ" ในที่นี้เรียกว่า "บริบทการดำเนินการ" อย่างมืออาชีพ แต่ด้วยการเพิ่มขึ้นของโค้ดปฏิบัติการเช่นฟังก์ชัน จะจัดการบริบทการดำเนินการจำนวนมากได้อย่างไร? ดังนั้นเอ็นจิ้น JS จึงสร้างแนวคิดของสแต็กบริบทการดำเนินการ
เราสามารถใช้อาร์เรย์เพื่อจำลองพฤติกรรมของมันได้อย่างสมบูรณ์ (มีบริบทการดำเนินการทั่วโลก globalContext ที่ด้านล่างของสแต็กเสมอ)
เรา
กำหนด
EStack อันดับแรก
EStack=[globalContext];
push(<checkscope> functionContext); EStack.push(<f> functionContext);EStack.pop();EStack.pop();
และโค้ดชิ้นที่สองเป็นดังนี้:
EStack.push(<checkscope> functionContext); EStack.pop();EStack.push (<f> functionContext);EStack.pop();
เหตุผลก็คือคุณอาจต้องศึกษาแนวคิดของ "การปิด" ก่อน!
อย่างไรก็ตาม จะบรรลุ "การประหยัดข้อมูลในระยะยาว" ใน "ส่วนหน้าแบบโมดูลาร์" ได้อย่างไร?
แคช? เลขที่ ปิด!
ประการแรก ขอบเขตหมายถึงพื้นที่ในโปรแกรมที่มีการกำหนดตัวแปร ขอบเขตระบุวิธีการค้นหาตัวแปร ซึ่งกำหนดสิทธิ์การเข้าถึงของโค้ดที่รันอยู่ในปัจจุบันไปยังตัวแปร
ขอบเขตมีสองประเภท: ขอบเขตคงที่ และ ขอบเขตแบบไดนามิก
ขอบเขตคงที่ที่ใช้โดย JS เรียกอีกอย่างว่า "ขอบเขตคำศัพท์" ขอบเขตของฟังก์ชันจะถูกกำหนดเมื่อมีการกำหนดฟังก์ชัน
จากที่กล่าวมาข้างต้น ตัวแปรในขอบเขตคำศัพท์จะมีขอบเขตที่แน่นอนในระหว่างกระบวนการคอมไพล์ ขอบเขตนี้คือ "บริบทการดำเนินการปัจจุบัน" หลังจาก ES5 เราใช้ "สภาพแวดล้อมคำศัพท์" แทนขอบเขตเพื่ออธิบายบริบทการดำเนินการ สภาพแวดล้อมคำศัพท์ประกอบด้วยสมาชิกสองคน:
ลองดูตัวอย่าง:
var value=1 ;ฟังก์ชั่น foo(){ console.log(ค่า);}แถบฟังก์ชัน(){ ค่า var=2; foo();}bar();
มองย้อนกลับไปที่คำจำกัดความข้างต้น ควรพิมพ์อะไร?
มาวิเคราะห์กระบวนการดำเนินการ:
ดำเนินการฟังก์ชัน foo() โดยค้นหาภายในฟังก์ชัน foo ก่อนเพื่อดูว่ามีค่าตัวแปรในเครื่องหรือไม่ ถ้าไม่ ให้มองหาโค้ดบนเลเยอร์ด้านบนตามตำแหน่งที่ถูกกำหนดไว้ นั่นคือ value=1 ดังนั้นผลลัพธ์จะถูกพิมพ์เป็น 1
แน่นอนว่านี่ไม่ใช่เรื่องง่ายนักและสามารถสรุปได้ คุณสามารถวิเคราะห์ได้จากมุมมองของบริบทการดำเนินการ
ข้างต้น เราได้พูดคุยเกี่ยวกับองค์ประกอบทั้งสองของสภาพแวดล้อมคำศัพท์ (ขอบเขต) เมื่อรวมกับบริบทการดำเนินการ ก็ไม่ยากที่จะพบว่าด้วยการอ้างอิงสภาพแวดล้อมคำศัพท์ภายนอก ขอบเขตสามารถขยายไปตามเลเยอร์สแต็กทีละเลเยอร์ สร้างโครงสร้างลูกโซ่ที่ขยายออกไปด้านนอกจากสภาพแวดล้อมปัจจุบัน
ลองดูตัวอย่างอื่น:
function foo(){ console.dir(บาร์); วาร์ a=1; แถบฟังก์ชัน(){ ก=2; }}console.dir(foo);foo();
จากขอบเขตคงที่ ฟังก์ชันส่วนกลาง foo จะสร้างแอตทริบิวต์ [[scope]]
ของวัตถุของตัวเอง
foo
[[scope]]=[globalContext];
( ) นอกจากนี้ยังจะเข้าสู่ระยะเวลาการกำหนดและระยะเวลาการดำเนินการของฟังก์ชัน foo อย่างต่อเนื่อง
ในช่วงระยะเวลาคำจำกัดความของฟังก์ชัน foo [[ขอบเขต]] ของแถบฟังก์ชันจะ
[[scope]]
ขอบเขตในตัวส่วนกลางและขอบเขตในตัวของ foo
bar[[scope]]=[fooContext,globalContext];
จุดนี้: "JS จะส่งผ่าน การอ้างอิงสภาพแวดล้อมคำศัพท์ภายนอกจะใช้เพื่อสร้างห่วงโซ่ขอบเขตของวัตถุตัวแปร ดังนั้นจึงรับประกันการเข้าถึงที่ได้รับคำสั่งไปยังตัวแปรและฟังก์ชันที่สภาพแวดล้อมการดำเนินการสามารถเข้าถึงได้ "
กลับไปที่คำถามในบริบทการดำเนินการ เรากล่าวไว้ก่อนหน้านี้ว่าอะไรคือความแตกต่างระหว่างพวกเขา เรามาพูดถึงสาเหตุที่พวกเขาพิมพ์ “local scope” ในลักษณะเดียวกัน: มันยังคงเป็นประโยคเดียวกัน “JS ใช้ lexical scope และขอบเขตของฟังก์ชันขึ้นอยู่กับตำแหน่งที่สร้างฟังก์ชัน ” - การดำเนินการของฟังก์ชัน JS มีการใช้ขอบเขตขอบเขตซึ่งถูกสร้างขึ้นเมื่อมีการกำหนดฟังก์ชัน ฟังก์ชันที่ซ้อนกัน f() ถูกกำหนดไว้ในห่วงโซ่ขอบเขตนี้ และขอบเขตตัวแปรในนั้นจะต้องอ้างอิงถึงตัวแปรในเครื่อง ไม่ว่าจะดำเนินการเมื่อใดและที่ไหน การผูกข้อมูลนี้ยังคงใช้ได้เมื่อดำเนินการ f()
เมื่อไม่พบตัวแปรในบันทึกสภาพแวดล้อมคำศัพท์ของตัวเอง ก็สามารถค้นหาตัวแปรนั้นไปยังเลเยอร์ภายนอกตามการอ้างอิงสภาพแวดล้อมคำศัพท์ภายนอก จนกว่าการอ้างอิงสภาพแวดล้อมคำศัพท์ภายนอกในสภาพแวดล้อมคำศัพท์ภายนอกสุดจะเป็น null
คล้ายกับสิ่งนี้คือ "การค้นหาตามสายโซ่ต้นแบบในวัตถุ":
__proto__
เป็นโมฆะ)ความแตกต่างก็ชัดเจนเช่นกัน: สายโซ่ต้นแบบคือลิงก์ที่สร้างการสืบทอดวัตถุผ่านแอตทริบิวต์ต้นแบบ ในขณะที่สายโซ่ขอบเขตอ้างถึงการปิดที่อนุญาตให้ฟังก์ชันภายในเข้าถึงฟังก์ชันภายนอก ไม่ว่าทางตรงหรือทางอ้อม สายขอบเขตฟังก์ชันทั้งหมดจะเชื่อมโยงกับบริบทระดับโลกในท้ายที่สุด
คำแนะนำที่เกี่ยวข้อง: บทช่วยสอนการเรียนรู้ JavaScript
ข้างต้นเป็นความเข้าใจเชิงลึกเกี่ยวกับวิธีการเรียกใช้งานโค้ด JS สำหรับข้อมูลเพิ่มเติม โปรดใส่ใจกับบทความอื่น ๆ ที่เกี่ยวข้องบนเว็บไซต์ภาษาจีน PHP