日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

JavaScript的预编译及执行顺序

發布時間:2025/6/17 javascript 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JavaScript的预编译及执行顺序 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

從JavaScript引擎的解析機制來探索JavaScript的工作原理,下面我們以更形象的示例來說明JavaScript代碼在頁面中的執行順序。

如果說,JavaScript引擎的工作機制比較深奧是因為它屬于底層行為,那么JavaScript代碼執行順序就比較形象了,因為我們可以直觀感覺到這種執行順序,當然JavaScript代碼的執行順序是比較復雜的,所以在深入JavaScript語言之前也有必要對其進行剖析。

1 按HTML文檔流順序執行JavaScript代碼

首先,讀者應該清楚,HTML文檔在瀏覽器中的解析過程是這樣的:瀏覽器是按著文檔流從上到下逐步解析頁面結構和信息的。

JavaScript代碼作為嵌入的腳本應該也算做HTML文檔的組成部分,所以JavaScript代碼在裝載時的執行順序也是根據腳本標簽<script>的出現順序來確定的。

例如,瀏覽下面文檔頁面,你會看到代碼是從上到下逐步被解析的。

<html> <head> <script type="text/javascript">alert("頭部腳本"); </script> <title></title> </head> <body> <script type="text/javascript">alert("頁面腳本"); </script> </body> <script type="text/javascript">alert("底部腳本"); </script> </html>

如果通過腳本標簽<script>的src屬性導入外部JavaScript文件腳本,那么它也將按照其語句出現的順序來執行,而且執行過程是文檔裝載的一部分。不會因為是外部JavaScript文件而延期執行。

例如,把上面文檔中的頭部和主體區域的腳本移到外部JavaScript文件中,然后通過src屬性導入。繼續預覽頁面文檔,你會看到相同的執行順序。

<html> <head> <script type="text/javascript">alert("頭部腳本"); </script> <title></title> </head> <body> <script type="text/javascript" src="body.js"></script> </body> <script type="text/javascript" src="bottom.js"></script> </html>

2 預編譯與執行順序的關系

當JavaScript引擎解析腳本時,它會在預編譯期對所有聲明的變量和函數進行處理。所以,就會出現當JavaScript解釋器執行下面腳本時不會報錯:

alert(a); // 返回值undefined var a =1; alert(a); // 返回值1

由于變量聲明是在預編譯期被處理的,所以在執行期間對于所有代碼來說,都是可見的。

但是,你也會看到,執行上面代碼,提示的值是undefined,而不是1。

這是因為,變量初始化過程發生在執行期,而不是預編譯期。

在執行期,JavaScript解釋器是按著代碼先后順序進行解析的,如果在前面代碼行中沒有為變量賦值,則JavaScript解釋器會使用默認值undefined。

由于在第二行中為變量a賦值了,所以在第三行代碼中會提示變量a的值為1,而不是undefined。

同理,下面示例在函數聲明前調用函數也是合法的,并能夠被正確解析,所以返回值為1。

f(); // 調用函數,返回值1 function f(){alert(1); }

但是,如果按下面方式定義函數,則JavaScript解釋器會提示語法錯誤。

f(); // 調用函數,返回語法錯誤 var f = function(){alert(1); }

這是函數聲明和函數表達式的區別,解析器在向執行環境中加載數據時,解析器會率先讀取函數聲明,并使其在執行任何代碼前可用; 至于函數表達式,則必須等到解析器執行到它所在的代碼行,才會真正被解析執行。

上面示例中定義的函數僅作為值賦值給變量f,所以在預編譯期,JavaScript解釋器只能夠為聲明變量f進行處理,而對于變量f的值,只能等到執行期時按順序進行賦值,自然就會出現語法錯誤,提示找不到對象f。

雖然變量和函數聲明可以在文檔任意位置,但是良好的習慣應該是在所有JavaScript代碼之前聲明全局變量和函數,并對變量進行初始化賦值。在函數內部也是先聲明變量,然后再引用。

3 按塊執行JavaScript代碼

所謂代碼塊就是使用<script>標簽分隔的代碼段。例如,下面兩個<script>標簽分別代表兩個JavaScript代碼塊。

<script type="text/javascript">// JavaScript代碼塊1var a =1; </script><script type="text/javascript">// JavaScript代碼塊2function f(){alert(1);} </script>

JavaScript解釋器在執行腳本時,是按塊來執行的。通俗地說,就是瀏覽器在解析HTML文檔流時,如果遇到一個<script>標簽,則JavaScript解釋器會等到這個代碼塊都加載完后,先對代碼塊進行預編譯,然后再執行。

執行完畢后,瀏覽器會繼續解析下面的HTML文檔流,同時JavaScript解釋器也準備好處理下一個代碼塊。

由于JavaScript是按塊執行的,所以如果在一個JavaScript塊中調用后面塊中聲明的變量或函數就會提示語法錯誤。

例如,當JavaScript解釋器執行下面代碼時就會提示語法錯誤,顯示變量a未定義,對象f找不到。

<script type="text/javascript">// JavaScript代碼塊1 alert(a);f(); </script> <script type="text/javascript">// JavaScript代碼塊2var a = 1;function f() {alert(1);} </script>

雖然說,JavaScript是按塊執行的,但是不同塊都屬于同一個全局作用域,也就是說,塊之間的變量和函數是可以共享的。

4 借助事件機制改變JavaScript執行順序

由于JavaScript是按塊處理代碼,同時又遵循HTML文檔流的解析順序,所以在上面示例中會看到這樣的語法錯誤。

但是當文檔流加載完畢,如果再次訪問就不會出現這樣的錯誤。例如,把訪問第2塊代碼中的變量和函數的代碼放在頁面初始化事件函數中,就不會出現語法錯誤了。

<script type="text/javascript"> // JavaScript代碼塊1 window.onload = function(){ // 頁面初始化事件處理函數 alert(a);f(); } </script><script type="text/javascript"> // JavaScript代碼塊2 var a =1; function f(){alert(1); } </script>

為了安全起見,我們一般在頁面初始化完畢之后才允許JavaScript代碼執行,這樣可以避免網速對JavaScript執行的影響,同時也避開了HTML文檔流對于JavaScript執行的限制。

注意

如果在一個頁面中存在多個windows.onload事件處理函數,則只有最后一個才是有效的,為了解決這個問題,可以把所有腳本或調用函數都放在同一個onload事件處理函數中,例如:

window.onload = function(){f1();f2();f3();}

而且通過這種方式可以改變函數的執行順序,方法是:簡單地調整onload事件處理函數中調用函數的排列順序。

除了頁面初始化事件外,我們還可以通過各種交互事件來改變JavaScript代碼的執行順序,如鼠標事件、鍵盤事件及時鐘觸發器等方法。

詳細講解請參閱《javascript征途》第14章的內容。

5 JavaScript輸出腳本的執行順序

在JavaScript開發中,經常會使用document對象的write()方法輸出JavaScript腳本。那么這些動態輸出的腳本是如何執行的呢?例如:

document.write('<script type="text/javascript">'); document.write('f(); '); document.write('function f(){ '); document.write(' alert(1); '); document.write('} '); document.write('<\/script> ');

運行上面代碼,我們會發現:document.write()方法先把輸出的腳本字符串寫入到腳本所在的文檔位置,瀏覽器在解析完document.write()所在文檔內容后,繼續解析document.write()輸出的內容,然后才按順序解析后面的HTML文檔。也就是說,JavaScript腳本輸出的代碼字符串會在輸出后馬上被執行。

請注意,使用document.write()方法輸出的JavaScript腳本字符串必須放在同時被輸出的<script>標簽中,否則JavaScript解釋器因為不能夠識別這些合法的JavaScript代碼,而作為普通的字符串顯示在頁面文檔中。例如,下面的代碼就會把JavaScript代碼顯示出來,而不是執行它。

document.write('f(); '); document.write('function f(){ '); document.write(' alert(1); '); document.write('); ');

但是,通過document.write()方法輸出腳本并執行也存在一定的風險,因為不同JavaScript引擎對其執行順序不同,同時不同瀏覽器在解析時也會出現Bug。

? 問題一,找不到通過document.write()方法導入的外部JavaScript文件中聲明的變量或函數。

例如,看下面示例代碼。

document.write('<script type="text/javascript" src="test.js"><\/script>'); document.write('<script type="text/javascript"> '); document.write('alert(n); '); // IE提示找不到變量n document.write('<\/script> '); alert(n+1); // 所有瀏覽器都會提示找不到變量
外部JavaScript文件(test.js)的代碼如下:

var n = 1;

分別在不同瀏覽器中進行測試,會發現提示語法錯誤,找不到變量n。也就是說,如果在JavaScript代碼塊中訪問本代碼塊中使用document.write()方法輸出的腳本中導入的外部JavaScript文件所包含的變量,會顯示語法錯誤。

同時,如果在IE瀏覽器中,不僅在腳本中,而且在輸出的腳本中也會提示找不到輸出的導入外部JavaScript文件的變量(表述有點長和繞,不懂的讀者可以嘗試運行上面代碼即可明白)。

? 問題二,不同JavaScript引擎對輸出的外部導入腳本的執行順序略有不同。例如,看下面示例代碼。

<script type="text/javascript">document.write('<script type="text/javascript" src="test1.js"><\/script>'); document.write('<script type="text/javascript"> '); document.write('alert(2);') document.write('alert(n+2);'); document.write('<\/script>'); </script> <script type="text/javascript"> alert(n+3); </script>

外部JavaScript文件(test1.js)的代碼如下所示。

var n = 1;

alert(n);

在IE瀏覽器中的執行順序如圖1-6所示。

圖1-6 IE 7瀏覽器的執行順序和提示的語法錯誤

在符合DOM標準的瀏覽器中的執行順序與IE瀏覽器不同,且沒有語法錯誤,如圖1-7所示的是在Firefox 3.0瀏覽器中的執行順序。

圖1-7 Firefox 3瀏覽器的執行順序和提示的語法錯誤

解決不同瀏覽器存在的不同執行順序,以及可能存在Bug。我們可以把凡是使用輸出腳本導入的外部文件,都放在獨立的代碼塊中,這樣根據上面介紹的JavaScript代碼塊執行順序,就可以避免這個問題。例如,針對上面示例,可以這樣設計:

<script type="text/javascript"> document.write('<script type="text/javascript" src="test1.js"><\/script>'); </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> <script type="text/javascript"> alert(n+4); // 提示5 </script>

這樣在不同瀏覽器中都能夠按順序執行上面代碼,且輸出順序都是1、2、3、4和5。存在問題的原因是:輸出導入的腳本與當前JavaScript代碼塊之間的矛盾。如果單獨輸出就不會發生沖突了。

轉自:http://ribbonchen.blog.163.com/blog/static/11831650520105220402832/

轉載于:https://www.cnblogs.com/v10258/archive/2013/04/25/3042248.html

總結

以上是生活随笔為你收集整理的JavaScript的预编译及执行顺序的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。