ในบทนำก่อนหน้านี้เรารู้อยู่แล้วว่า JavaScript ไม่มีฟังก์ชั่นระดับบล็อกเพียงขอบเขตระดับฟังก์ชั่น
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่นทดสอบ () {// a ขอบเขต
สำหรับ (var i = 0; i <10; i ++) {// ไม่ใช่ขอบเขต
// นับ
-
console.log (i); // 10
-
นอกจากนี้ยังไม่มีเนมสเปซที่แสดงในจาวาสคริปต์ซึ่งหมายความว่าทุกอย่างถูกกำหนดไว้ในขอบเขตทั่วโลก ทุกครั้งที่มีการอ้างอิงตัวแปร JavaScript จะสำรวจขอบเขตทั่วโลกทั้งหมดจนกว่าจะพบ หากตัวแปรยังไม่พบผ่านขอบเขตทั่วโลกเต็มรูปแบบข้อผิดพลาดของ ReferenceRror จะถูกโยนลงไป
กรุณากรอกคำอธิบายรูปภาพ
ตัวแปรทั่วโลกโดยนัย
การคัดลอกรหัสมีดังนี้:
// สคริปต์ก
foo = '42';
// สคริปต์ B
var foo = '42'
สองตัวอย่างข้างต้นมีผลกระทบที่แตกต่างกัน ครั้งแรกจะกำหนดตัวแปร foo ในขอบเขตทั่วโลกในขณะที่ที่สองจะกำหนดตัวแปร foo ในขอบเขตปัจจุบัน
เราต้องทราบว่าหากคุณไม่ใช้คำหลัก VAR มันจะมีผลกระทบที่ไม่คาดคิด
การคัดลอกรหัสมีดังนี้:
// ขอบเขตทั่วโลก
var foo = 42;
ฟังก์ชั่นทดสอบ () {
// ขอบเขตท้องถิ่น
foo = 21;
-
ทดสอบ();
ฟู; // 21
เนื่องจาก VAR ไม่ได้ใช้เพื่อกำหนดตัวแปร FOO ในการทดสอบฟังก์ชั่นตัวแปร Global Foo นอกฟังก์ชั่นจะถูกเขียนทับ แม้ว่ามันจะไม่เป็นปัญหาใหญ่หากมีรหัสหลายพันบรรทัด แต่มันจะเป็นข้อผิดพลาดที่ยากในการติดตาม
การคัดลอกรหัสมีดังนี้:
// ขอบเขตทั่วโลก
รายการ var = [/ * บางรายการ */];
สำหรับ (var i = 0; i <10; i ++) {
subloop ();
-
ฟังก์ชั่น subloop () {
// ขอบเขตของ subloop
สำหรับ (i = 0; i <10; i ++) {// คำสั่ง var ที่หายไป
// ทำสิ่งที่น่าทึ่ง!
-
-
ในตัวอย่างข้างต้นลูปภายนอกจะหยุดลงเมื่อการดำเนินการครั้งแรกถูกดำเนินการเนื่องจากตัวแปร I ภายในฟังก์ชั่น Subloop จะแทนที่ตัวแปร Global External Global I เราจำเป็นต้องเพิ่ม var ภายในฟังก์ชั่นเพื่อหลีกเลี่ยงข้อผิดพลาดนี้ดังนั้นเราต้องไม่ลืมเพิ่มคำหลัก var เมื่อกำหนดตัวแปร เว้นแต่ว่าเราต้องการมีผลกระทบต่อตัวแปรทั่วโลกภายนอก
ตัวแปรท้องถิ่น
ตัวแปรท้องถิ่นใน JavaScript สามารถสร้างได้ในสองวิธีเท่านั้นหนึ่งจะถูกประกาศผ่านคำหลัก var และอื่น ๆ ใช้เป็นพารามิเตอร์ที่เป็นทางการของฟังก์ชัน
การคัดลอกรหัสมีดังนี้:
// ขอบเขตทั่วโลก
var foo = 1;
var bar = 2;
var i = 2;
การทดสอบฟังก์ชั่น (i) {
// ขอบเขตท้องถิ่นของการทดสอบฟังก์ชั่น
i = 5;
var foo = 3;
บาร์ = 4;
-
ทดสอบ (10);
ในเวลานี้ตัวแปร I และ FOO ภายในการทดสอบฟังก์ชั่นเป็นตัวแปรท้องถิ่นและแถบจะแทนที่แถบตัวแปรทั่วโลกภายนอก
การยก
JavaScript จะส่งเสริมการประกาศตัวแปรซึ่งหมายความว่าทั้งการแสดงออกของ VAR และการประกาศฟังก์ชั่นจะได้รับการส่งเสริมให้อยู่ในระดับสูงสุดของขอบเขต
การคัดลอกรหัสมีดังนี้:
บาร์();
var bar = function () {};
var somevalue = 42;
ทดสอบ();
การทดสอบฟังก์ชั่น (ข้อมูล) {
ถ้า (เท็จ) {
Goo = 1;
} อื่น {
var goo = 2;
-
สำหรับ (var i = 0; i <100; i ++) {
var e = data [i];
-
-
ก่อนที่จะเรียกใช้รหัสข้างต้นการประกาศการแสดงออกของ VAR และการทดสอบฟังก์ชั่นจะได้รับการเลื่อนตำแหน่งไปด้านบนดังนั้นโปรแกรมจะทำงานตามปกติและจะไม่รายงานข้อผิดพลาด
การคัดลอกรหัสมีดังนี้:
// คำสั่ง VAR ถูกย้ายมาที่นี่
var bar, somevalue; // ค่าเริ่มต้นเป็น 'ไม่ได้กำหนด'
// การประกาศฟังก์ชั่นก็ขยับขึ้นเช่นกัน
การทดสอบฟังก์ชั่น (ข้อมูล) {
var goo, i, e; // ขอบเขตบล็อกที่หายไปเคลื่อนย้ายสิ่งเหล่านี้ที่นี่
ถ้า (เท็จ) {
Goo = 1;
} อื่น {
Goo = 2;
-
สำหรับ (i = 0; i <100; i ++) {
e = data [i];
-
-
บาร์(); // ล้มเหลวด้วย typeError เนื่องจากแถบยังคง 'ไม่ได้กำหนด'
somevalue = 42; // การมอบหมายไม่ได้รับผลกระทบจากการยก
bar = function () {};
ทดสอบ();
เนื่องจาก JavaScript ไม่มีขอบเขตระดับบล็อกสิ่งนี้จะไม่เพียง แต่ปรับปรุงการแสดงออกของ VAR แต่ยังทำให้โครงสร้าง IF ใช้งานง่าย
ในตัวอย่างข้างต้นแม้ว่าจะดูเหมือนว่าหากทำงานบนสารตัวแปรทั่วโลกในความเป็นจริงเนื่องจากตัวแปร goo ได้รับการส่งเสริมตัวแปรท้องถิ่นจะถูกแก้ไข
หากคุณไม่มีความเข้าใจเกี่ยวกับกฎระดับความสูงคุณอาจคิดว่ารหัสต่อไปนี้จะส่งข้อผิดพลาดอ้างอิง
การคัดลอกรหัสมีดังนี้:
// ตรวจสอบว่ามีการเริ่มต้นหรือไม่
ถ้า (! สิ่งที่สำคัญบางอย่าง) {
var someimportantthing = {};
-
แน่นอนรหัสข้างต้นไม่ผิดเพราะนิพจน์ VAR ได้รับการเลื่อนตำแหน่งไปด้านบนก่อนที่รหัสจะทำงาน
การคัดลอกรหัสมีดังนี้:
var บางสิ่งที่สำคัญ;
// รหัสอื่นอาจเริ่มต้นสิ่งสำคัญบางอย่างที่นี่หรือไม่
// ตรวจสอบให้แน่ใจว่าอยู่ที่นั่น
ถ้า (! สิ่งที่สำคัญบางอย่าง) {
บางสิ่งที่สำคัญ = {};
-
ที่นี่ฉันอยากจะแนะนำโพสต์บล็อกของแฟน ๆ @Nightire Fan "การทำความเข้าใจ JavaScript (II)" ซึ่งอธิบายการปรับปรุงอย่างละเอียดมาก
คำสั่งความละเอียดของชื่อ
เมื่อพยายามเข้าถึงตัวแปร FOO ภายในขอบเขตฟังก์ชัน JavaScript จะค้นหาตามลำดับต่อไปนี้:
ไม่ว่าจะมีคำจำกัดความของ var foo ในขอบเขตปัจจุบัน
ไม่ว่าจะมีตัวแปร FOO ในพารามิเตอร์ฟังก์ชันหรือไม่
ไม่ว่าจะเป็นฟังก์ชั่นตัวเองหรือไม่
ข้ามไปที่โดเมนนิยามด้านนอกและเริ่มค้นหาจากส่วนแรก
เนมสเปซ
หนึ่งในปัญหาที่พบบ่อยที่สุดคือการตั้งชื่อความขัดแย้งเนื่องจาก JavaScript มีขอบเขตระดับโลกเพียงอันเดียว แต่ปัญหานี้สามารถแก้ไขได้โดยฟังก์ชั่นภายนอกที่ไม่ระบุชื่อ
การคัดลอกรหัสมีดังนี้:
(การทำงาน() {
// ตัวเองมี "เนมสเปซ"
window.foo = function () {
// การปิดที่เปิดเผย
-
- // ดำเนินการฟังก์ชั่นทันที
ฟังก์ชั่นที่ไม่ระบุชื่อในตัวอย่างข้างต้นถือเป็นนิพจน์ดังนั้นพวกเขาจึงถูกดำเนินการ
การคัดลอกรหัสมีดังนี้:
(// ประเมินฟังก์ชั่นภายในผู้ปกครอง
การทำงาน() {}
) // และส่งคืนวัตถุฟังก์ชัน
() // เรียกผลลัพธ์ของการประเมินผล
แน่นอนว่าเรายังสามารถใช้วิธีการอื่น ๆ ในการเรียกใช้ฟังก์ชั่นการแสดงออกโครงสร้างที่แตกต่างกัน แต่เอฟเฟกต์เดียวกัน
การคัดลอกรหัสมีดังนี้:
// รูปแบบอื่น ๆ สองสามข้อสำหรับเรียกใช้โดยตรง
!การทำงาน(){}()
+function () {} ()
(การทำงาน(){}());
// และอื่น ๆ ...
สรุป
ขอแนะนำให้คุณใช้ฟังก์ชั่นภายนอกที่ไม่ระบุชื่อเพื่อห่อหุ้มรหัสลงในพื้นที่ซึ่งไม่เพียง แต่แก้ปัญหาความขัดแย้งของเนมสเปซ แต่ยังช่วยอำนวยความสะดวกในการแยกส่วนของโปรแกรม
นอกจากนี้การใช้ตัวแปรระดับโลกไม่ใช่นิสัยที่ดีซึ่งจะนำค่าใช้จ่ายในการบำรุงรักษาสูงและมีแนวโน้มที่จะเกิดข้อผิดพลาด
เนมสเปซมีประเภทฟังก์ชั่นตัวแปรเทมเพลต ฯลฯ ทั้งหมดเป็นของเอนทิตี
คนธรรมดาสามัญของเอนทิตีคือมันสามารถมีชื่อได้ (นอกจากนี้แท็กยังสามารถมีชื่อได้ แต่ไม่ใช่เอนทิตี)
ขอบเขตเนมสเปซเป็นคำศัพท์ทั่วไปในขอบเขตซึ่งขนานกับขอบเขตบล็อกขอบเขตของคลาสขอบเขตของฟังก์ชันต้นแบบและขอบเขตฟังก์ชัน (ใช้ได้เฉพาะกับป้ายกำกับ) ชื่อที่ประกาศภายในเนมสเปซอยู่ในขอบเขตของเนมสเปซ ชื่อทั่วโลกได้รับการพิจารณาในขอบเขตเนมสเปซทั่วโลกโดยนัย
ฟังก์ชั่นของเนมสเปซนั้นมีขอบเขตแน่นอน แต่มันแตกต่างจากขอบเขตง่าย ๆ คุณสามารถประกาศเนมสเปซเดียวกันได้หลายแห่งในหลาย ๆ ครั้ง แต่เนื้อหาภายในไม่สามารถนิยามใหม่ได้ ในที่สุดพวกเขาจะสังเคราะห์เนมสเปซเช่นเดียวกับ STD, คำจำกัดความแมโครทุกที่