เนื้อหาหลัก:
1. วิเคราะห์ความหมายของขอบเขตคำศัพท์ JavaScript
2. แยกวิเคราะห์ห่วงโซ่ขอบเขตของตัวแปร
3. จะเกิดอะไรขึ้นเมื่อมีการเลื่อนชื่อตัวแปร?
เมื่อเร็วๆ นี้ ฉันกำลังอธิบายหลักสูตร JavaScript ใน Chuanzhi Podcast เพื่อนหลายคนรู้สึกว่า JavaScript นั้นเรียบง่ายมาก แต่พวกเขาไม่รู้ว่าจะใช้งานอย่างไร ดังนั้นฉันจึงเตรียมเนื้อหาบางส่วนมาแบ่งปันกับคุณ
ซีรีส์นี้จะอธิบายส่วนขั้นสูงของ JavaScript เป็นหลัก รวมถึงขอบเขตเชน การปิด รูปแบบการเรียกใช้ฟังก์ชัน ต้นแบบ และสิ่งที่เกี่ยวกับวัตถุ ไม่รวมไวยากรณ์พื้นฐานของ JavaScript ที่นี่ หากคุณต้องการทราบข้อมูลเบื้องต้น : ไปที่ //net.itcast.cn เพื่อดาวน์โหลดวิดีโอฟรีเพื่อการเรียนรู้ เอาล่ะ มาดูหัวข้อของเรากันดีกว่า
1. เกี่ยวกับขอบเขตระดับบล็อก
เมื่อพูดถึงขอบเขตตัวแปรของ JavaScript มันแตกต่างจากภาษาที่คล้าย C ที่เรามักใช้
ตัวอย่างเช่น รหัสต่อไปนี้ใน C#:
คัดลอกรหัสรหัสดังต่อไปนี้:
โมฆะคงที่หลัก (สตริง [] args)
-
ถ้า(จริง)
-
จำนวน int = 10;
-
System.Console.WriteLine (หมายเลข);
-
หากคอมไพล์โค้ดนี้จะไม่ผ่านเนื่องจาก "ไม่มีชื่อ num ในบริบทปัจจุบัน" เพราะที่นี่
ขอบเขตของตัวแปรถูกจำกัดด้วยเครื่องหมายปีกกา และเรียกว่าขอบเขตระดับบล็อก
ในขอบเขตระดับบล็อก ตัวแปรทั้งหมดจะอยู่ภายในเครื่องหมายปีกกาของคำจำกัดความ ตั้งแต่จุดเริ่มต้นของคำจำกัดความไปจนถึงจุดสิ้นสุดของเครื่องหมายปีกกา
สามารถใช้ได้ภายในขอบเขต ไม่สามารถเข้าถึงได้นอกขอบเขตนี้ กล่าวคือ รหัส
คัดลอกรหัสรหัสดังต่อไปนี้:
ถ้า(จริง)
-
จำนวน int = 10;
System.Console.WriteLine (หมายเลข);
-
สามารถเข้าถึงได้ที่นี่เนื่องจากมีการกำหนดและใช้ตัวแปรภายในวงเล็บปีกกาเดียวกัน
แต่มันแตกต่างใน JavaScript ไม่มีแนวคิดเกี่ยวกับขอบเขตระดับบล็อกใน JavaScript
2. ขอบเขตใน JavaScript
ใน JavaScript รหัสต่อไปนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
ถ้า(จริง) {
วาร์นัม = 10;
-
การแจ้งเตือน (หมายเลข);
ผลลัพธ์ของการดำเนินการคือหน้าต่างป๊อปอัป 10 แล้วขอบเขตของตัวแปรใน JavaScript ถูกจำกัดอย่างไร?
2.1 ฟังก์ชั่นจำกัดขอบเขตตัวแปร
ใน JavaScript มีเพียงฟังก์ชันเท่านั้นที่สามารถจำกัดขอบเขตของตัวแปรได้ นั่นหมายความว่าอย่างไร
กล่าวคือ ใน JavaScript ตัวแปรที่กำหนดภายในฟังก์ชันสามารถเข้าถึงได้ภายในฟังก์ชัน แต่เข้าถึงภายนอกฟังก์ชันได้
ไม่สามารถเข้าถึงได้ ดูรหัสต่อไปนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
var func = ฟังก์ชั่น () {
วาร์นัม = 10;
-
พยายาม {
การแจ้งเตือน (หมายเลข);
} จับ (จ) {
การแจ้งเตือน (e);
-
เมื่อโค้ดนี้ถูกรัน ข้อยกเว้นจะถูกส่งออกไป และตัวแปร num จะไม่ถูกกำหนดไว้ กล่าวอีกนัยหนึ่งคือ ตัวแปรที่กำหนดในฟังก์ชันไม่สามารถทำได้
ใช้นอกฟังก์ชัน แน่นอนว่าสามารถใช้งานได้อย่างอิสระภายในฟังก์ชัน ก่อนกำหนด ดูโค้ดต่อไปนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
var func = ฟังก์ชั่น () {
การแจ้งเตือน (หมายเลข);
วาร์นัม = 10;
การแจ้งเตือน (หมายเลข);
-
พยายาม {
ฟังก์ชั่น();
} จับ (จ) {
การแจ้งเตือน (e);
-
หลังจากรันโค้ดนี้แล้ว จะไม่มีข้อผิดพลาดเกิดขึ้น และหน้าต่างป๊อปอัปจะปรากฏขึ้นสองครั้ง โดยไม่ได้กำหนดและ 10 ตามลำดับ (สำหรับสาเหตุ ฉันจะอธิบายด้านล่าง)
จากที่นี่จะเห็นได้ว่าตัวแปรสามารถเข้าถึงได้ภายในฟังก์ชันเท่านั้น ในทำนองเดียวกัน ฟังก์ชันภายในฟังก์ชันก็สามารถเข้าถึงได้เช่นกัน
2.2 โดเมนย่อยเข้าถึงโดเมนหลัก
ตามที่กล่าวไว้ข้างต้น ฟังก์ชันสามารถจำกัดขอบเขตของตัวแปร ดังนั้นฟังก์ชันในฟังก์ชันจึงกลายเป็นโดเมนย่อยของขอบเขตในโดเมนย่อย
รหัสในสามารถเข้าถึงตัวแปรในโดเมนหลัก ดูรหัสต่อไปนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
var func = ฟังก์ชั่น () {
วาร์นัม = 10;
var sub_func = ฟังก์ชั่น() {
การแจ้งเตือน (หมายเลข);
-
sub_func();
-
ฟังก์ชั่น();
ผลลัพธ์ของการรันโค้ดนี้คือ 10 คุณสามารถดูการเข้าถึงตัวแปรที่กล่าวถึงข้างต้น แต่เมื่อเข้าถึงโดเมนหลักในโดเมนลูก
รหัสยังมีเงื่อนไขเช่นรหัสต่อไปนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
var func = ฟังก์ชั่น () {
วาร์นัม = 10;
var sub_func = ฟังก์ชั่น() {
วาร์นัม = 20;
การแจ้งเตือน (หมายเลข);
-
sub_func();
-
ฟังก์ชั่น();
รหัสนี้มี "var num = 20" มากกว่าเมื่อก่อน รหัสนี้อยู่ในโดเมนย่อย ดังนั้นโดเมนย่อยจะเข้าถึงโดเมนหลัก
มีการเปลี่ยนแปลง ผลลัพธ์ที่พิมพ์โดยรหัสนี้คือ 20 นั่นคือจำนวนที่โดเมนย่อยเข้าถึงได้ในขณะนี้เป็นตัวแปรในโดเมนย่อย ไม่ใช่โดเมนหลัก
จะเห็นได้ว่ามีกฎเกณฑ์บางประการสำหรับการเข้าถึง เมื่อใช้ตัวแปรใน JavaScript ล่าม JavaScript ก่อน
ค้นหาโดเมนผู้ใช้เพื่อดูว่ามีคำจำกัดความของตัวแปรหรือไม่ ถ้ามี ให้ใช้ตัวแปรนี้ หากไม่มี ให้ค้นหาตัวแปรในโดเมนหลัก
โดยการเปรียบเทียบ จนกว่าจะไม่พบขอบเขตระดับบนสุด ข้อยกเว้น "ไม่ได้กำหนดตัวแปร" จะถูกส่งออกไป ดูรหัสต่อไปนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
(การทำงาน() {
วาร์นัม = 10;
(การทำงาน() {
วาร์นัม = 20;
(การทำงาน(){
การแจ้งเตือน (หมายเลข);
-
-
-
หลังจากดำเนินการโค้ดนี้แล้ว 20 จะถูกพิมพ์ ถ้า "var num = 20;" จะถูกลบออก เช่นเดียวกัน ถ้า "var num = 20;"
"var num = 10" จากนั้นจะเกิดข้อผิดพลาดที่ไม่ได้กำหนดไว้
3. ขอบเขตขอบเขต
ด้วยการแบ่งขอบเขต JavaScript ขอบเขตการเข้าถึง JavaScript จึงสามารถเชื่อมต่อเข้ากับโครงสร้างแผนผังแบบลูกโซ่ได้
เมื่อเข้าใจขอบเขตของ JavaScript ได้อย่างชัดเจนแล้ว ตัวแปรและการปิดของ JavaScript ก็จะมีความชัดเจนมาก
วิธีการต่อไปนี้ใช้การวาดเพื่อวาดห่วงโซ่ขอบเขต
3.1 กฎการวาด:
1) ห่วงโซ่ขอบเขตคืออาร์เรย์ของวัตถุ
2) สคริปต์ทั้งหมดอยู่ในห่วงโซ่ระดับ 0 แต่ละวัตถุครอบครองหนึ่งตำแหน่ง
3) เมื่อใดก็ตามที่คุณเห็นฟังก์ชั่นขยายออกไปเป็นลูกโซ่ ให้ขยายมันทีละระดับ
4) เมื่อเข้าถึง ให้ดูที่ฟังก์ชันปัจจุบันก่อน หากไม่ได้กำหนด ให้ตรวจสอบห่วงโซ่
5) ทำซ้ำจนกระทั่งห่วงโซ่ระดับ 0
3.2 ตัวอย่าง
ดูรหัสด้านล่าง:
คัดลอกรหัสรหัสดังต่อไปนี้:
วาร์นัม = 10;
var func1 = ฟังก์ชั่น() {
วาร์นัม = 20;
var func2 = ฟังก์ชั่น() {
วาร์นัม = 30;
การแจ้งเตือน (หมายเลข);
-
func2();
-
var func2 = ฟังก์ชั่น() {
วาร์นัม = 20;
var func3 = ฟังก์ชั่น() {
การแจ้งเตือน (หมายเลข);
-
func3();
-
func1();
func2();
มาวิเคราะห์โค้ดนี้กัน:
-> ก่อนอื่น โค้ดทั้งหมดเป็นขอบเขตส่วนกลางและสามารถทำเครื่องหมายเป็นลูกโซ่ขอบเขตระดับ 0 ได้ จากนั้นจะมีอาร์เรย์
var link_0 = [num, func1, func2];//อธิบายไว้ที่นี่ด้วยโค้ดเทียม
-> ที่นี่ func1 และ func2 เป็นฟังก์ชันทั้งคู่ ดังนั้นจึงได้รับขอบเขตเชนระดับ 1 สองอัน กล่าวคือ
var link_1 = { func1: [ num, func2 ] }; // อธิบายไว้ที่นี่ด้วยโค้ดเทียม
var link_1 = { func2: [ num, func3 ] }; // อธิบายไว้ที่นี่ด้วยรหัสหลอก
-> ห่วงโซ่ระดับ 1 แรกได้มาจากห่วงโซ่ระดับ 2
var link_2 = { func2: [ num ] }; // อธิบายไว้ที่นี่ด้วยรหัสหลอก
-> เชนระดับ 1 ที่สองไม่มีการกำหนดตัวแปรและเป็นเชนว่างซึ่งแสดงเป็น
var link_2 = { func3: [ ] };
-> ด้วยการรวมโค้ดข้างต้น ขอบเขตขอบเขตสามารถแสดงเป็น:
คัดลอกรหัสรหัสดังต่อไปนี้:
//อธิบายไว้ที่นี่ด้วยรหัสเทียม
var link = [ // เชนระดับ 0
หมายเลข
{ func1 : [ // เชนระดับ 1 แรก
หมายเลข
{ func2 : [ // เชนระดับ 2
จำนวน
-
-
{ func2 : [ // เชนระดับ 1 ที่สอง
หมายเลข
{ func3 : [] }
-
-
-> แสดงเป็นรูปภาพเป็น
รูป: 01_01 ขอบเขต chain.bmp
หมายเหตุ: ใช้โค้ด js เพื่อแสดงแผนภาพลูกโซ่ และจะชัดเจนมากเมื่อไฮไลต์
ด้วยแผนภาพลูกโซ่ขอบเขตนี้ คุณจะเข้าใจวิธีการเข้าถึงตัวแปรได้อย่างชัดเจน:
เมื่อคุณต้องการใช้ตัวแปร ให้ค้นหาตัวแปรในเชนปัจจุบันก่อน หากคุณพบ ให้ใช้โดยตรง
ค้นหาขึ้นไป หากไม่พบ ให้ค้นหาห่วงโซ่ขอบเขตหนึ่งระดับไปจนถึงห่วงโซ่ขอบเขต 0
หากคุณสามารถกำหนดระดับของห่วงโซ่ขอบเขตของตัวแปรได้อย่างชัดเจน จากนั้นเมื่อทำการวิเคราะห์ JavaScript
มันง่ายมากเมื่อพูดถึงการเขียนโค้ดและการใช้ฟีเจอร์ JavaScript ขั้นสูง เช่น การปิด (อย่างน้อยสำหรับฉัน)
3. การส่งเสริมชื่อตัวแปรและการส่งเสริมชื่อฟังก์ชัน
ด้วยขอบเขตโซ่และกฎการเข้าถึงตัวแปร มีปัญหายุ่งยากมาก มาดูสิ่งต่อไปนี้กันก่อน
รหัสจาวาสคริปต์:
คัดลอกรหัสรหัสดังต่อไปนี้:
วาร์นัม = 10;
var func = ฟังก์ชั่น () {
การแจ้งเตือน (หมายเลข);
วาร์นัม = 20;
การแจ้งเตือน (หมายเลข);
-
ฟังก์ชั่น();
ผลการดำเนินการจะเป็นอย่างไร? ลองคิดดูนะครับผมยังไม่เปิดเผยคำตอบ
มาวิเคราะห์โค้ดนี้กันก่อน
มีห่วงโซ่ขอบเขตระดับ 0 ในโค้ดนี้ ซึ่งประกอบด้วยหมายเลขสมาชิกและ func ภายใต้ func จะมีฟังก์ชันระดับ 1
Domain chain ซึ่งมีหมายเลขสมาชิก ดังนั้น เมื่อเรียกใช้ฟังก์ชัน func ก็จะตรวจพบว่าอยู่ในขอบเขตปัจจุบัน
ตัวแปร num ถูกกำหนดไว้แล้ว ดังนั้นตัวแปรนี้จะถูกนำมาใช้ อย่างไรก็ตาม num ยังไม่ได้กำหนดค่าในขณะนี้ เนื่องจากโค้ด
รหัสรันจากบนลงล่าง ดังนั้น การพิมพ์ครั้งแรกจึงไม่ได้กำหนดไว้ และการพิมพ์ครั้งที่สองคือ 20
คุณเข้าใจถูกแล้วใช่ไหม?
เป็นเรื่องปกติใน JavaScript ที่จะกำหนดโค้ดที่ด้านหลังและใช้ที่ด้านหน้าเช่นนี้
คำถาม ณ เวลานี้เหมือนกับว่าตัวแปรถูกกำหนดไว้ตั้งแต่ต้นและผลลัพธ์ก็เหมือนกับโค้ดต่อไปนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
วาร์นัม = 10;
var func = ฟังก์ชั่น () {
var num;// รู้สึกเหมือนถูกกำหนดไว้ที่นี่ แต่ไม่มีการกำหนด
การแจ้งเตือน (หมายเลข);
วาร์นัม = 20;
การแจ้งเตือน (หมายเลข);
-
ฟังก์ชั่น();
ปรากฏการณ์นี้มักเรียกว่าการเลื่อนชื่อตัวแปร นอกจากนี้ยังมีการเลื่อนชื่อฟังก์ชันด้วย ตัวอย่างเช่น รหัสต่อไปนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
var func = ฟังก์ชั่น () {
alert("เรียกใช้ฟังก์ชันภายนอก");
-
var foo = ฟังก์ชั่น() {
ฟังก์ชั่น();
var func = ฟังก์ชั่น () {
alert("เรียกใช้ฟังก์ชันภายใน");
-
ฟังก์ชั่น();
-
โอเค รหัสนี้มีลักษณะอย่างไร? หรือน่าจะมีอะไรแตกต่างออกไปก็ไม่ปล่อยให้ผู้อ่านคิดหรอก!
ฉันจะให้คำตอบในบทความถัดไป
เนื่องจากความแตกต่างเหล่านี้ ในระหว่างการพัฒนาจริง ขอแนะนำให้เขียนตัวแปรทั้งหมดตั้งแต่ต้น
กล่าวคือ ตัวแปรถูกกำหนดไว้ที่จุดเริ่มต้นของฟังก์ชัน คล้ายกับข้อกำหนดของภาษา C ซึ่งก็เป็นจริงในไลบรารี js เช่นกัน
เสร็จเรียบร้อยแล้ว เช่น jQuery เป็นต้น
4. สรุป
โอเค บทความนี้จะอธิบายเป็นหลักว่าขอบเขตคำศัพท์ของ JavaScript คืออะไร และคำอธิบายด้วย
จะวิเคราะห์ห่วงโซ่ขอบเขตและสถานะการเข้าถึงของตัวแปรได้อย่างไร มาทำแบบฝึกหัดกันอีกครั้ง! - -
ดูว่าผลลัพธ์ของการรันโค้ดด้านล่างคืออะไร:
คัดลอกรหัสรหัสดังต่อไปนี้:
if( ! "a" ในหน้าต่าง) {
var a = "กำหนดตัวแปร";
-
การแจ้งเตือน (ก);