簡體   English   中英

在瀏覽器中為單個網頁執行了多少個JavaScript程序?

[英]How many JavaScript programs are executed for a single web-page in the browser?

JavaScript程序由語句和函數聲明組成。 執行JavaScript程序時,會執行以下兩個步驟:

  1. 掃描代碼以查找函數聲明和每個函數。 聲明是“執行”(通過創建一個函數對象),並創建一個對該函數的命名引用(以便可以在語句中調用此函數)

  2. 語句按順序執行(評估)(因為它們出現在代碼中)

因此,這很好用

<script>
    foo();
    function foo() {
        return;
    }
</script>

雖然“foo”函數在聲明之前被調用,但它起作用,因為函數聲明在語句之前被計算。

但是,這不起作用

<script>
    foo();
</script>
<script>
    function foo() {
        return;
    }
</script>

拋出ReferenceError(“foo未定義”)。 這導致得出結論,Web頁面的HTML代碼中的每個SCRIPT元素代表一個單獨的JavaScript程序,並且每次HTML解析器遇到SCRIPT元素時,它都會執行該元素內的程序(然后一旦程序執行,解析器轉到SCRIPT元素后面的HTML代碼。

然后,這確實有效

<script>
    function foo() {
        return;
    }
</script>
<script>
    foo();
</script>

我的理解是Global對象(在全局執行上下文中充當Variable對象)始終存在(並保持),因此第一個JavaScript程序將創建函數對象並為其創建引用,然后第二個JavaScript程序將使用該引用來調用該函數。 因此,所有JavaScript程序(在單個Web頁面中)“使用​​”相同的Global對象,並且隨后運行的所有JavaScript程序都可以觀察到一個JavaScript程序對Global對象所做的所有更改。

現在,請注意這個......

<script>
    // assuming that foo is not defined
    foo();
    alert(1);
</script>

在上面的例子中,警報調用將不會執行 ,因為“foo()”語句拋出一個ReferenceError(它會破壞整個JavaScript程序),因此,所有后續語句都不會執行。

但是,在這種情況下......

<script>
    // assuming that foo is not defined
    foo();
</script>
<script>
    alert(1);
</script>

現在,警報調用確實已執行 第一個JavaScript程序拋出一個ReferenceError(並因此中斷),但第二個JavaScript程序正常運行。 當然,瀏覽器會報告錯誤(盡管它在錯誤發生后確實執行了后續的JavaScript程序)。

現在,我的結論是:

  • Web頁面的HTML代碼中的每個SCRIPT元素代表一個單獨的JavaScript程序。 這些程序在HTML解析器遇到它們時立即執行。
  • 同一個網頁中的所有JavaScript程序都“使用”相同的Global對象。 Global對象始終存在(從提取Web頁面到銷毀Web頁面的那一刻)。 JavaScript程序可以操作Global對象,並且可以在所有后續JavaScript程序中觀察由一個JavaScript程序對Global對象所做的所有更改。
  • 如果一個JavaScript程序中斷(通過拋出錯誤),這不會阻止后續JavaScript程序執行。

請事實查看這篇文章並告訴我是否有錯誤。

此外,我沒有找到解釋本文中提到的行為的資源,我認為瀏覽器制造商必須在某處發布此類資源,因此如果您了解它們,請提供相關鏈接。

函數提升 - 在function其余部分之前評估function語句的過程 - 是ECMAScript標准IIRC的一部分(我現在找不到引用,但我記得看到EMCAScript的討論提到它)。 script標記的評估是HTML標准的一部分。 它沒有指定它們是如此多的單詞中的“單獨程序”,但它確實表示腳本元素按照它們在文檔中出現的順序進行評估。 這就是為什么以后的腳本標記中的函數不會被掛起的原因:該腳本尚未被評估。 這也解釋了為什么一個腳本停止不會切斷后續腳本:當前腳本停止評估時,下一個腳本開始。

Dmitry Soshnikov回答了你的問題。 每個<script>元素都作為程序執行,由ECMAScript規范定義。 單個頁面中的每個程序都使用一個全局對象。 這就是它。

它們是單獨的程序,但它們修改共享的全局對象。

另一種思考方式是偽本地范圍和全局范圍。 每個SCRIPT聲明都具有其當前方法/功能的本地范圍,以及對當前(先前聲明的)全局范圍的訪問。 每當在SCRIPT塊中定義方法/函數時,它就會被添加到全局范圍,並在其后可由SCRIPT塊訪問。

另外,這里是W3C對腳本聲明/處理/修改的進一步參考:

文檔的動態修改可以建模如下:

  1. 在加載文檔時,將按順序評估所有SCRIPT元素。
  2. 將評估生成SGML CDATA的給定SCRIPT元素中的所有腳本構造。 將它們組合生成的文本插入到文檔中以代替SCRIPT元素。
  3. 生成的CDATA被重新評估。

是腳本/功能評估/聲明的另一個好資源。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM