ก่อนหน้านี้ เราได้ศึกษาหลักการทำงานของ JavaScript จากกลไกการแยกวิเคราะห์ของเอ็นจิ้น JavaScript ตอนนี้เราใช้ตัวอย่างที่ชัดเจนมากขึ้นเพื่อแสดงลำดับการดำเนินการของโค้ด JavaScript บนเพจ หากกลไกการทำงานของกลไก JavaScript ค่อนข้างลึกซึ้งเนื่องจากเป็นของพฤติกรรมพื้นฐาน ลำดับการดำเนินการของโค้ด JavaScript จะชัดเจนยิ่งขึ้น เนื่องจากเราสามารถสัมผัสได้ถึงลำดับการดำเนินการของโค้ด JavaScript โดยสัญชาตญาณ มีความซับซ้อนมากขึ้น ดังนั้นจึงจำเป็นต้องสร้างโปรไฟล์ภาษา JavaScript ก่อนที่จะเจาะลึกลงไป
1.1 รันโค้ด JavaScript ตามลำดับการไหลของเอกสาร HTML
ก่อนอื่น ผู้อ่านควรรู้ว่ากระบวนการแยกวิเคราะห์เอกสาร HTML ในเบราว์เซอร์มีดังนี้ เบราว์เซอร์จะค่อยๆ แยกวิเคราะห์โครงสร้างหน้าและข้อมูลจากบนลงล่างตามการไหลของเอกสาร รหัส JavaScript ซึ่งเป็นสคริปต์ที่ฝังไว้ควรนับเป็นส่วนประกอบของเอกสาร HTML ดังนั้นลำดับการดำเนินการของโค้ด JavaScript ในระหว่างการโหลดจึงถูกกำหนดตามลำดับที่แท็กสคริปต์ <script> ปรากฏขึ้นด้วย ตัวอย่างเช่น เรียกดูหน้าเอกสารประกอบด้านล่าง และคุณจะเห็นว่ามีการแยกวิเคราะห์โค้ดทีละขั้นตอนจากบนลงล่าง
คัดลอกรหัสรหัสดังต่อไปนี้:
<สคริปต์>
alert("สคริปต์ยอดนิยม");
</สคริปต์>
<html><หัว>
<สคริปต์>
alert("สคริปต์ส่วนหัว");
</สคริปต์>
<title></title>
</หัว>
<ร่างกาย>
<สคริปต์>
alert("สคริปต์เพจ");
</สคริปต์>
</body></html>
<สคริปต์>
alert("สคริปต์ด้านล่าง");
</สคริปต์>
หากนำเข้าสคริปต์ไฟล์ JavaScript ภายนอกผ่านแอตทริบิวต์ src ของแท็กสคริปต์ <script> สคริปต์นั้นจะถูกดำเนินการตามลำดับที่คำสั่งปรากฏขึ้นด้วย และกระบวนการดำเนินการเป็นส่วนหนึ่งของการโหลดเอกสาร การดำเนินการจะไม่ล่าช้าเนื่องจากเป็นไฟล์ JavaScript ภายนอก ตัวอย่างเช่น ย้ายสคริปต์ในพื้นที่ส่วนหัวและเนื้อหาของเอกสารด้านบนไปยังไฟล์ JavaScript ภายนอก จากนั้นนำเข้าสคริปต์ผ่านแอตทริบิวต์ src ดูตัวอย่างเอกสารหน้าต่อไป คุณจะเห็นลำดับการดำเนินการเดียวกัน
คัดลอกรหัสรหัสดังต่อไปนี้:
<สคริปต์>
alert("สคริปต์ยอดนิยม");
</สคริปต์>
<html>
<หัว>
<script src="//www.VeVB.COm/head.js"></script>
<title></title>
</หัว>
<ร่างกาย>
<script src="//www.VeVB.COm/body.js"></script>
</ร่างกาย>
</html>
<สคริปต์>
alert("สคริปต์ด้านล่าง");
</สคริปต์>
1.2 ความสัมพันธ์ระหว่างการคอมไพล์ล่วงหน้าและลำดับการดำเนินการ
ใน Javascript ฟังก์ชันคือ Javascript ประเภทแรก เมื่อเราเขียนฟังก์ชัน จริงๆ แล้วเรากำลังสร้างเอนทิตีประเภทฟังก์ชันเท่านั้น
เช่นเดียวกับที่เราเขียนได้ในรูปแบบนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
ฟังก์ชั่นสวัสดี()
-
alert("สวัสดี");
-
สวัสดี();
varHello = ฟังก์ชั่น()
-
alert("สวัสดี");
-
สวัสดี();
ในความเป็นจริงพวกเขาทั้งหมดเหมือนกัน แต่เมื่อเราปรับเปลี่ยนฟังก์ชั่นเราจะพบปัญหาที่แปลกมาก
คัดลอกรหัสรหัสดังต่อไปนี้:
<scripttype="text/javascript">
functionHello() {
alert("สวัสดี");
-
สวัสดี();
functionHello() {
alert("สวัสดีชาวโลก");
-
สวัสดี();
</สคริปต์>
เราจะเห็นผลลัพธ์ดังนี้: Hello World ส่งออกสองครั้งติดต่อกัน
แทนที่จะเป็น Hello และ Hello World ที่เราจินตนาการไว้
เนื่องจาก Javascript ไม่ได้รับการตีความและดำเนินการตามลำดับอย่างสมบูรณ์ แต่ Javascript จะถูก "คอมไพล์แล้ว" ก่อนการตีความ ในระหว่างกระบวนการคอมไพล์ล่วงหน้า ฟังก์ชันที่กำหนดไว้จะถูกดำเนินการก่อน และตัวแปร var ทั้งหมดจะถูกสร้างขึ้น โดยไม่ได้กำหนดค่าเริ่มต้นไว้เพื่อปรับปรุง ประสิทธิภาพการทำงานของโปรแกรม
กล่าวอีกนัยหนึ่ง โค้ดข้างต้นได้รับการคอมไพล์ล่วงหน้าโดยเอ็นจิ้น JS ในรูปแบบนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
<scripttype="text/javascript">
varHello = ฟังก์ชั่น() {
alert("สวัสดี");
-
สวัสดี = ฟังก์ชั่น () {
alert("สวัสดีชาวโลก");
-
สวัสดี();
สวัสดี();
</สคริปต์>
จากโค้ดข้างต้นเราสามารถเห็นได้ชัดเจนว่าฟังก์ชันต่างๆ นั้นเป็นข้อมูลและตัวแปรด้วย นอกจากนี้เรายังสามารถกำหนดค่า (กำหนดใหม่) ให้กับ "ฟังก์ชัน" ได้อีกด้วย
แน่นอน เพื่อป้องกันสถานการณ์นี้ เรายังสามารถทำได้:
คัดลอกรหัสรหัสดังต่อไปนี้:
<scripttype="text/javascript">
functionHello() {
alert("สวัสดี");
-
สวัสดี();
</สคริปต์>
<scripttype="text/javascript">
functionHello() {
alert("สวัสดีชาวโลก");
-
สวัสดี();
</สคริปต์>
ด้วยวิธีนี้ โปรแกรมจะแบ่งออกเป็นสองส่วน และกลไก JS จะไม่รวมเข้าด้วยกัน
เมื่อเอ็นจิ้น JavaScript แยกวิเคราะห์สคริปต์ มันจะประมวลผลตัวแปรและฟังก์ชันที่ประกาศไว้ทั้งหมดในระหว่างการคอมไพล์ล่วงหน้า
ทำสิ่งต่อไปนี้:
1. ก่อนการดำเนินการ การดำเนินการที่คล้ายกับ "การคอมไพล์ล่วงหน้า" จะดำเนินการ: ขั้นแรก จะมีการสร้างออบเจ็กต์ที่ใช้งานอยู่ในสภาพแวดล้อมการดำเนินการปัจจุบัน และตัวแปรเหล่านั้นที่ประกาศด้วย var จะถูกตั้งค่าเป็นแอตทริบิวต์ของออบเจ็กต์ที่ใช้งานอยู่ แต่ในขณะนี้ การกำหนดตัวแปรเหล่านี้จะไม่ได้ถูกกำหนดไว้ และฟังก์ชันเหล่านั้นที่กำหนดด้วยฟังก์ชันจะถูกเพิ่มเป็นคุณสมบัติของวัตถุที่ใช้งานอยู่ด้วย และค่าของพวกมันคือคำจำกัดความของฟังก์ชันอย่างแน่นอน
2. ในระหว่างขั้นตอนการตีความและการดำเนินการ เมื่อจำเป็นต้องแยกวิเคราะห์ตัวแปร ตัวแปรนั้นจะถูกค้นหาจากออบเจ็กต์ที่ใช้งานอยู่ของสภาพแวดล้อมการดำเนินการปัจจุบันก่อน หากไม่พบและเจ้าของสภาพแวดล้อมการดำเนินการมีแอตทริบิวต์ต้นแบบ จะถูกค้นหาจากห่วงโซ่ต้นแบบ มิฉะนั้น จะถูกค้นหาตามขอบเขต เมื่อพบคำสั่ง เช่น var a = ... ตัวแปรที่เกี่ยวข้องจะถูกกำหนดค่า (หมายเหตุ: การกำหนดตัวแปรจะเสร็จสิ้นในระหว่างขั้นตอนการตีความและการดำเนินการ หากใช้ตัวแปรก่อนหน้านี้ ค่าของตัวแปรจะเป็น ไม่ได้กำหนดไว้) ดังนั้น จะปรากฏว่าจะไม่มีการรายงานข้อผิดพลาดเมื่อล่าม JavaScript รันสคริปต์ต่อไปนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
alert(a); // คืนค่าไม่ได้กำหนด
วาร์ ก =1;
alert(a); // ส่งคืนค่า 1
เนื่องจากการประกาศตัวแปรได้รับการประมวลผลในเวลาที่คอมไพล์ล่วงหน้า โค้ดทั้งหมดจึงสามารถมองเห็นได้ในระหว่างการดำเนินการ อย่างไรก็ตาม คุณจะเห็นว่าเมื่อรันโค้ดข้างต้น ค่าที่แจ้งไม่ได้ถูกกำหนดไว้ ไม่ใช่ 1 เนื่องจากกระบวนการเริ่มต้นตัวแปรเกิดขึ้นระหว่างการดำเนินการ ไม่ใช่การคอมไพล์ล่วงหน้า ในระหว่างการดำเนินการ ล่าม JavaScript จะแยกวิเคราะห์รหัสตามลำดับ หากไม่มีการกำหนดค่าตัวแปรในบรรทัดก่อนหน้าของโค้ด ล่าม JavaScript จะใช้ค่าเริ่มต้นเป็น undefinition เนื่องจากตัวแปร a ได้รับการกำหนดค่าในบรรทัดที่สอง โค้ดบรรทัดที่สามจะแจ้งว่าค่าของตัวแปร a เป็น 1 ไม่ใช่ไม่ได้กำหนด
ในทำนองเดียวกัน ในตัวอย่างต่อไปนี้ การเรียกใช้ฟังก์ชันก่อนที่จะประกาศฟังก์ชันนั้นถูกต้องตามกฎหมายและสามารถแยกวิเคราะห์ได้อย่างถูกต้อง ดังนั้นค่าที่ส่งคืนคือ 1
คัดลอกรหัสรหัสดังต่อไปนี้:
f(); // ฟังก์ชันการโทรคืนค่า 1
ฟังก์ชัน ฉ(){
การแจ้งเตือน (1);
-
อย่างไรก็ตาม หากมีการกำหนดฟังก์ชันดังต่อไปนี้ ตัวแปล JavaScript จะแจ้งข้อผิดพลาดทางไวยากรณ์
คัดลอกรหัสรหัสดังต่อไปนี้:
f(); // ฟังก์ชันการโทรและส่งคืนข้อผิดพลาดทางไวยากรณ์
var f = ฟังก์ชัน(){
การแจ้งเตือน (1);
-
เนื่องจากฟังก์ชันที่กำหนดไว้ในตัวอย่างข้างต้นถูกกำหนดให้กับตัวแปร f เป็นค่าเท่านั้น ดังนั้น ในระหว่างช่วงก่อนการคอมไพล์ ล่าม JavaScript สามารถประมวลผลการประกาศตัวแปร f เท่านั้น และค่าของตัวแปร f สามารถทำได้เท่านั้น จะถูกกดในระหว่างช่วงดำเนินการ หากดำเนินการตามลำดับ จะเกิดข้อผิดพลาดทางไวยากรณ์โดยธรรมชาติ ซึ่งบ่งชี้ว่าไม่พบวัตถุ f
ลาก่อนตัวอย่างบางส่วน:
คัดลอกรหัสรหัสดังต่อไปนี้:
<script type="text/javascript">
/*ในระหว่างกระบวนการคอมไพล์ล่วงหน้า func เป็นคุณลักษณะในอ็อบเจ็กต์ที่ใช้งานอยู่ในสภาพแวดล้อมของหน้าต่าง และค่าคือฟังก์ชันที่ครอบคลุมค่าที่ไม่ได้กำหนด*/
alert(func); //function func(){alert("สวัสดี!")}
var func = "นี่คือตัวแปร"
ฟังก์ชั่น func(){
การแจ้งเตือน ("สวัสดี!")
-
/*ระหว่างดำเนินการ var ถูกพบและถูกกำหนดใหม่เป็น "นี่คือตัวแปร"*/
alert(func); //นี่คือตัวแปร
</สคริปต์>
คัดลอกรหัสรหัสดังต่อไปนี้:
<script type="text/javascript">
ชื่อ var = "feng"; ฟังก์ชั่น func()
-
/*ขั้นแรก กำหนดชื่อให้กับ undefine ในสภาพแวดล้อม func จากนั้นค้นหาแอตทริบิวต์ name ของอ็อบเจ็กต์ที่ใช้งานอยู่ในสภาพแวดล้อม func ระหว่างการดำเนินการ ในขณะนี้ ค่าได้ถูกคอมไพล์ล่วงหน้าเป็น undefinition ดังนั้นเอาต์พุตจึงไม่ได้ถูกกำหนดไว้ เฟิง */
การแจ้งเตือน (ชื่อ); // ไม่ได้กำหนด var name = "JSF";
การแจ้งเตือน (ชื่อ); //JSF
-
ฟังก์ชั่น();
การแจ้งเตือน (ชื่อ);
//เฟิง
</สคริปต์>
แม้ว่าการประกาศตัวแปรและฟังก์ชันสามารถอยู่ที่ใดก็ได้ในเอกสาร แต่แนวทางปฏิบัติที่ดีในการประกาศตัวแปรและฟังก์ชันโกลบอลก่อนโค้ด JavaScript ทั้งหมด และการเริ่มต้นและกำหนดตัวแปร ภายในฟังก์ชัน ตัวแปรจะถูกประกาศก่อนแล้วจึงอ้างอิง
1.3 รันโค้ด JavaScript ในบล็อก
บล็อกโค้ดที่เรียกว่าคือส่วนของโค้ดที่คั่นด้วยแท็ก <script> ตัวอย่างเช่น แท็ก <script> สองแท็กด้านล่างแสดงถึงบล็อกโค้ด JavaScript สองบล็อก
คัดลอกรหัสรหัสดังต่อไปนี้:
<สคริปต์>
// บล็อกโค้ด JavaScript 1
วาร์ ก =1;
</สคริปต์>
<สคริปต์>
// บล็อกโค้ด JavaScript 2
ฟังก์ชัน ฉ(){
การแจ้งเตือน (1);
-
</สคริปต์>
เมื่อล่าม JavaScript รันสคริปต์ มันจะรันสคริปต์เป็นบล็อก ในแง่ของคนธรรมดา หากเบราว์เซอร์พบแท็ก <script> เมื่อแยกวิเคราะห์สตรีมเอกสาร HTML ตัวแปล JavaScript จะรอจนกว่าบล็อกโค้ดจะถูกโหลด ขั้นแรกให้คอมไพล์บล็อกโค้ดล่วงหน้า จากนั้นจึงดำเนินการ หลังจากดำเนินการ เบราว์เซอร์ยังคงแยกวิเคราะห์สตรีมเอกสาร HTML ด้านล่าง และล่าม JavaScript ก็พร้อมที่จะประมวลผลโค้ดบล็อกถัดไป
เนื่องจาก JavaScript ดำเนินการในบล็อก หากคุณเรียกใช้ตัวแปรหรือฟังก์ชันที่ประกาศในบล็อกถัดไปในบล็อก JavaScript ระบบจะแจ้งข้อผิดพลาดทางไวยากรณ์ ตัวอย่างเช่น เมื่อล่าม JavaScript รันโค้ดต่อไปนี้ จะแจ้งข้อผิดพลาดทางไวยากรณ์ โดยแสดงว่าตัวแปร a ไม่ได้ถูกกำหนดไว้ และไม่พบวัตถุ f
คัดลอกรหัสรหัสดังต่อไปนี้:
<สคริปต์>
// บล็อกโค้ด JavaScript 1
การแจ้งเตือน (ก);
ฉ();
</สคริปต์>
<สคริปต์>
// บล็อกโค้ด JavaScript 2
วาร์ ก =1;
ฟังก์ชัน ฉ(){
การแจ้งเตือน (1);
-
</สคริปต์>
แม้ว่า JavaScript จะดำเนินการในบล็อก แต่บล็อกที่แตกต่างกันจะอยู่ในขอบเขตส่วนกลางเดียวกัน ซึ่งหมายความว่าตัวแปรและฟังก์ชันระหว่างบล็อกสามารถแชร์ได้
1.4 ใช้กลไกเหตุการณ์เพื่อเปลี่ยนลำดับการทำงานของ JavaScript
เนื่องจาก JavaScript ประมวลผลโค้ดเป็นส่วนๆ และทำตามลำดับการแยกวิเคราะห์ของโฟลว์เอกสาร HTML คุณจะเห็นข้อผิดพลาดทางไวยากรณ์ดังกล่าวในตัวอย่างด้านบน แต่เมื่อโหลดสตรีมเอกสารแล้ว ข้อผิดพลาดดังกล่าวจะไม่เกิดขึ้นหากมีการเข้าถึงอีกครั้ง ตัวอย่างเช่น หากโค้ดที่เข้าถึงตัวแปรและฟังก์ชันในบล็อกที่สองของโค้ดถูกวางไว้ในฟังก์ชันเหตุการณ์การเริ่มต้นหน้า จะไม่มีข้อผิดพลาดทางไวยากรณ์
คัดลอกรหัสรหัสดังต่อไปนี้:
<สคริปต์>
// บล็อกโค้ด JavaScript 1
window.onload = function(){ // ฟังก์ชันการจัดการเหตุการณ์การเริ่มต้นหน้า
การแจ้งเตือน (ก);
ฉ();
-
</สคริปต์>
<สคริปต์>
// บล็อกโค้ด JavaScript 2
วาร์ ก =1;
ฟังก์ชัน ฉ(){
การแจ้งเตือน (1);
-
</สคริปต์>
ด้วยเหตุผลด้านความปลอดภัย โดยทั่วไปเราอนุญาตให้เรียกใช้โค้ด JavaScript หลังจากที่เริ่มต้นเพจแล้วเท่านั้น ซึ่งสามารถหลีกเลี่ยงผลกระทบของความเร็วเครือข่ายต่อการทำงานของ JavaScript และยังหลีกเลี่ยงข้อจำกัดในการดำเนินการ JavaScript ที่เกิดจากโฟลว์เอกสาร HTML
สังเกต
หากมีตัวจัดการเหตุการณ์ windows.onload หลายตัวในเพจ เฉพาะอันสุดท้ายเท่านั้นที่ถูกต้อง ในการแก้ปัญหานี้ คุณสามารถใส่สคริปต์ทั้งหมดหรือฟังก์ชันการเรียกใช้ในตัวจัดการเหตุการณ์ onload เดียวกันได้ ตัวอย่างเช่น:
คัดลอกรหัสรหัสดังต่อไปนี้:
window.onload = ฟังก์ชั่น () {
f1();
f2();
f3();
-
และด้วยวิธีนี้ ลำดับการดำเนินการของฟังก์ชันสามารถเปลี่ยนแปลงได้โดยเพียงแค่ปรับลำดับของการเรียกใช้ฟังก์ชันในตัวจัดการเหตุการณ์ onload
นอกเหนือจากเหตุการณ์การเริ่มต้นเพจแล้ว เรายังสามารถเปลี่ยนลำดับการดำเนินการของโค้ด JavaScript ผ่านเหตุการณ์เชิงโต้ตอบต่างๆ เช่น เหตุการณ์เมาส์ เหตุการณ์คีย์บอร์ด ทริกเกอร์นาฬิกา ฯลฯ สำหรับคำอธิบายโดยละเอียด โปรดดูบทที่ 14
1.5 ลำดับการดำเนินการของสคริปต์เอาต์พุต JavaScript
ในการพัฒนาจาวาสคริปต์ เมธอด write() ของอ็อบเจ็กต์เอกสารมักใช้เพื่อส่งออกสคริปต์จาวาสคริปต์ สคริปต์เอาต์พุตแบบไดนามิกเหล่านี้ดำเนินการอย่างไร ตัวอย่างเช่น:
คัดลอกรหัสรหัสดังต่อไปนี้:
document.write('<script type="text/javascript">');
document.write('f();');
document.write('ฟังก์ชั่น f(){');
document.write('alert(1);');
document.write('}');
document.write('</script>');
เมื่อรันโค้ดข้างต้น เราจะพบว่า: วิธี document.write() เขียนสตริงสคริปต์เอาต์พุตไปยังตำแหน่งเอกสารที่มีสคริปต์อยู่ หลังจากแยกวิเคราะห์เนื้อหาของเอกสารที่มี document.write() อยู่ เบราว์เซอร์ยังคงแยกวิเคราะห์ document.write () เนื้อหาที่ส่งออกแล้วแยกวิเคราะห์เอกสาร HTML ที่ตามมาตามลำดับ กล่าวอีกนัยหนึ่ง เอาต์พุตสตริงโค้ดโดยสคริปต์ JavaScript จะถูกดำเนินการทันทีหลังจากเอาต์พุต
โปรดทราบว่าจะต้องวางเอาต์พุตสตริงสคริปต์ JavaScript โดยใช้เมธอด document.write() ไว้ในแท็ก <script> ที่เอาต์พุตพร้อมกัน มิฉะนั้นล่าม JavaScript จะไม่สามารถจดจำรหัส JavaScript ทางกฎหมายเหล่านี้ได้ และจะเป็น แสดงเป็นสตริงปกติในเอกสารหน้า ตัวอย่างเช่น โค้ดต่อไปนี้จะแสดงโค้ด JavaScript แทนที่จะดำเนินการ
คัดลอกรหัสรหัสดังต่อไปนี้:
document.write('f();');
document.write('ฟังก์ชั่น f(){');
document.write('alert(1);');
document.write(');');
อย่างไรก็ตาม มีความเสี่ยงบางประการในการส่งออกและเรียกใช้สคริปต์ผ่านเมธอด document.write() เนื่องจากเอ็นจิ้น JavaScript ที่แตกต่างกันเรียกใช้งานสคริปต์ในลำดับที่แตกต่างกัน และจุดบกพร่องอาจเกิดขึ้นในเบราว์เซอร์ที่แตกต่างกันในระหว่างการแยกวิเคราะห์
Ø ปัญหาที่ 1: ไม่พบตัวแปรหรือฟังก์ชันที่ประกาศในไฟล์ JavaScript ภายนอกที่นำเข้าผ่านเมธอด document.write() ตัวอย่างเช่น ดูโค้ดตัวอย่างด้านล่าง
คัดลอกรหัสรหัสดังต่อไปนี้:
document.write('<script type="text/javascript" src="//www.VeVB.COm/test.js">
</สคริปต์>');
document.write('<script type="text/javascript">');
document.write('alert(n);'); // IE แจ้งว่าไม่พบตัวแปร n
document.write('</script>');
alert(n+1); // เบราว์เซอร์ทั้งหมดจะแจ้งว่าไม่พบตัวแปร n
รหัสของไฟล์ JavaScript ภายนอก (test.js) เป็นดังนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
วาร์ n = 1;
เมื่อทดสอบในเบราว์เซอร์ที่แตกต่างกัน คุณจะพบข้อผิดพลาดทางไวยากรณ์และไม่พบตัวแปร n กล่าวอีกนัยหนึ่ง หากคุณเข้าถึงตัวแปรที่มีอยู่ในไฟล์ JavaScript ภายนอกที่นำเข้าในเอาต์พุตสคริปต์ในบล็อกโค้ด JavaScript โดยใช้เมธอด document.write() ในบล็อกโค้ดนี้ ข้อผิดพลาดทางไวยากรณ์จะปรากฏขึ้น ในเวลาเดียวกัน หากในเบราว์เซอร์ IE ไม่เพียงแต่ในสคริปต์เท่านั้น แต่ยังอยู่ในสคริปต์เอาต์พุตด้วย ระบบจะแจ้งว่าไม่พบตัวแปรเอาต์พุตที่นำเข้าสู่ไฟล์ JavaScript ภายนอก (นิพจน์จะยาวและซับซ้อนเล็กน้อย ผู้อ่านที่ไม่เข้าใจสามารถลองรันโค้ดข้างต้นได้ก็สามารถเข้าใจได้)
Ø คำถามที่ 2: กลไก JavaScript ที่แตกต่างกันมีลำดับการดำเนินการที่แตกต่างกันเล็กน้อยสำหรับเอาต์พุตสคริปต์นำเข้าภายนอก ตัวอย่างเช่น ดูโค้ดตัวอย่างด้านล่าง
คัดลอกรหัสรหัสดังต่อไปนี้:
<script type="text/javascript">
document.write('<script type="text/javascript" src="http://shaozhuqing.com/test1.js">
</สคริปต์>');
document.write('<script type="text/javascript">');
document.write('alert(2);')
document.write('alert(n+2);');
document.write('</script>');
</สคริปต์>
<script type="text/javascript">
การแจ้งเตือน(n+3);
</สคริปต์>
รหัสสำหรับไฟล์ JavaScript ภายนอก (test1.js) แสดงอยู่ด้านล่าง
คัดลอกรหัสรหัสดังต่อไปนี้:
วาร์ n = 1;
การแจ้งเตือน (n);
ลำดับการดำเนินการในเบราว์เซอร์ IE แสดงในรูปที่ 1-6
รูปที่ 1-6 ลำดับการดำเนินการและข้อผิดพลาดทางไวยากรณ์ที่ได้รับแจ้งจากเบราว์เซอร์ IE 7
ลำดับการดำเนินการในเบราว์เซอร์ที่สอดคล้องกับมาตรฐาน DOM นั้นแตกต่างจากในเบราว์เซอร์ IE และไม่มีข้อผิดพลาดทางไวยากรณ์ รูปที่ 1-7 แสดงลำดับการดำเนินการในเบราว์เซอร์ Firefox 3.0
รูปที่ 1-7 ลำดับการดำเนินการเบราว์เซอร์ Firefox 3 และข้อผิดพลาดทางไวยากรณ์แจ้ง
แก้ไขลำดับการดำเนินการที่แตกต่างกันของเบราว์เซอร์ที่แตกต่างกันและข้อบกพร่องที่อาจเกิดขึ้น เราสามารถใส่ไฟล์ภายนอกทั้งหมดที่นำเข้าโดยใช้สคริปต์เอาท์พุตลงในบล็อคโค้ดอิสระ เพื่อให้สามารถหลีกเลี่ยงปัญหานี้ได้ตามลำดับการดำเนินการของบล็อคโค้ด JavaScript ที่แนะนำข้างต้น ตัวอย่างเช่น สำหรับตัวอย่างข้างต้น คุณสามารถออกแบบได้ดังนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
<script type="text/javascript">
document.write('<script type="text/javascript" src="//www.VeVB.COm/test1.js"></script>');
</สคริปต์>
<script type="text/javascript">
document.write('<script type="text/javascript">');
document.write('alert(2);') ; // เคล็ดลับ 2
document.write('alert(n+2);'); // เคล็ดลับ 3
document.write('</script>');
alert(n+3); // เคล็ดลับ 4
</สคริปต์>
<script type="text/javascript">
alert(n+4); // เคล็ดลับ 5
</สคริปต์>
ด้วยวิธีนี้ โค้ดด้านบนสามารถดำเนินการตามลำดับในเบราว์เซอร์ที่แตกต่างกัน และลำดับเอาต์พุตคือ 1, 2, 3, 4 และ 5 สาเหตุของปัญหาคือ: ข้อขัดแย้งระหว่างสคริปต์ที่นำเข้าเอาต์พุตและบล็อกโค้ด JavaScript ปัจจุบัน หากแยกเอาต์พุตจะไม่เกิดข้อขัดแย้ง