欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

瀏覽器環(huán)境下JavaScript腳本加載與執(zhí)行探析之動(dòng)態(tài)腳本與Ajax腳本注入

 更新時(shí)間:2016年01月19日 09:22:38   作者:TracyLin  
這篇文章主要介紹了瀏覽器環(huán)境下JavaScript腳本加載與執(zhí)行探析之動(dòng)態(tài)腳本與Ajax腳本注入 的相關(guān)資料,需要的朋友可以參考下

在《瀏覽器環(huán)境下JavaScript腳本加載與執(zhí)行探析之defer與async特性》中,我們研究了延遲腳本(defer)和異步腳本(async)的執(zhí)行時(shí)機(jī)、瀏覽器支持情況、瀏覽器bug以及其他的細(xì)節(jié)問題。而除了defer和async特性,動(dòng)態(tài)腳本和Ajax腳本注入也是兩種常用的創(chuàng)建無阻塞腳本的方法。總的來看,這兩種方法都能達(dá)到腳本加載不影響頁面解析和渲染的作用,但是在不同的瀏覽器中,這兩種技術(shù)所創(chuàng)建的腳本的執(zhí)行時(shí)機(jī)還是有一定差異,今天我們?cè)賮硖接懸幌峦ㄟ^動(dòng)態(tài)腳本技術(shù)和Ajax注入的腳本在這些方面的特性。

代碼準(zhǔn)備:

我們使用《瀏覽器環(huán)境下JavaScript腳本加載與執(zhí)行探析之代碼執(zhí)行順序》2.3節(jié)中的loadScript函數(shù)來添加動(dòng)態(tài)腳本,同時(shí)使用這篇文章2.4節(jié)中的loadXhrScript函數(shù)來實(shí)現(xiàn)Ajax腳本注入。我們把這兩個(gè)函數(shù)都放在util.js中。

另外,本文使用的CHROME的版本為47.0.2526.80,firefox的版本為43.0.4,opera版本為30.0.1835.125。

1 動(dòng)態(tài)腳本

1.1動(dòng)態(tài)腳本的執(zhí)行時(shí)機(jī)問題

我們?cè)凇稙g覽器環(huán)境下JavaScript腳本加載與執(zhí)行探析之defer與async特性》中2.3節(jié)DEMO的基礎(chǔ)上,增加三個(gè)外部js文件:

dynamic1.js

test += "我是head外部動(dòng)態(tài)腳本\n";

dynamic2.js

test += "我是body外部動(dòng)態(tài)腳本\n";

dynamic3.js

test += "我是底部外部動(dòng)態(tài)腳本\n";

1.1.1 DEMO1:動(dòng)態(tài)腳本的執(zhí)行時(shí)機(jī)初探

HTML的代碼為:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-"/>
<title>Dynamic Script Test</title>
<script src="http://lib.sinaapp.com/js/jquery/../jquery-...min.js"></script>
<script src="util.js"></script>
<script type="text/javascript">var test = "";</script>
<script>
loadScript("dynamic.js");
</script>
<script>
test += "我是head內(nèi)部腳本\n";
</script>
<script src=".js" type="text/javascript"></script>
</head>
<body>
<button id="test">點(diǎn)擊一下</button>
<script>
loadScript("dynamic.js");
</script>
<script src=".js" type="text/javascript"></script>
</body>
<script>
loadScript("dynamic.js");
</script>
<script src=".js" type="text/javascript"></script>
<script>
$(function(){
test += "我是DOMContentLoaded里面的腳本\n";
})
window.onload = function(){
test += "我是window.onload里面的腳本\n";
var button = document.getElementById("test");
button.onclick = function(){
console.log(test);
}
}
</script> 

在代碼中,我們先后將3個(gè)動(dòng)態(tài)腳本文件加入到HTML的<head>標(biāo)簽中,同時(shí)通過與正常外部腳本和內(nèi)部腳本的執(zhí)行來進(jìn)行比較,我們看一下不同瀏覽器中的執(zhí)行結(jié)果:

注:firefox和opera中執(zhí)行結(jié)果可能會(huì)變化

從上面的例子中,我們可以看出,在不同瀏覽器中,動(dòng)態(tài)腳本的執(zhí)行時(shí)機(jī)差異還是比較大的,但以下兩點(diǎn)是可以明確的:

[1]動(dòng)態(tài)腳本確實(shí)可以起到不阻塞后續(xù)腳本的作用,即延遲作用,但是這個(gè)延遲作用卻不一定能夠持續(xù)到所有的正常腳本都執(zhí)行完畢之后,也無法保證能夠延遲到DOMContentLoaded之后

[2]動(dòng)態(tài)腳本執(zhí)行的先后順序是無法保證的,這一點(diǎn)在http://www.dbjr.com.cn/article/77920.htm這篇文章以及后續(xù)的幾篇文章中進(jìn)行了詳細(xì)的解釋

從這個(gè)DEMO中還可以看出,動(dòng)態(tài)腳本的執(zhí)行時(shí)機(jī)具有較大的不確定性,雖然在DEMO1中,動(dòng)態(tài)腳本都在DOMContentLoaded事件之后執(zhí)行,但卻也并不意味著動(dòng)態(tài)腳本就不會(huì)阻塞DOMContentLoaded,我們通過DEOM2來看一下:

1.1.2 DEMO2:動(dòng)態(tài)腳本對(duì)DOMContentLoaded的阻塞

我們把DEMO1中的第27行內(nèi)碼修改為:

<script src="/delayfile.php?url=http://localhost/js/load/3.js&delay=5" type="text/javascript"></script> 

我們利用《瀏覽器環(huán)境下JavaScript腳本加載與執(zhí)行探析之代碼執(zhí)行順序》中的delayfile.php,將3.js的返回延遲5秒鐘,我們知道,如果是defer延遲腳本,無論正常外部腳本延遲了多長(zhǎng)時(shí)間,defer腳本還是會(huì)在正常外部腳本之后執(zhí)行的,但是動(dòng)態(tài)腳本卻不是這樣了,我們看一下修改后的代碼在瀏覽器中的執(zhí)行順序:


注:firefox和opera中執(zhí)行結(jié)果可能會(huì)變化

可以看到,在某個(gè)正常腳本加載時(shí)間較長(zhǎng)的時(shí)候,動(dòng)態(tài)腳本的執(zhí)行明顯提前,無論在IE還是CHROME、firefox和opera中,均在DOMContentLoaded之前執(zhí)行,因此我們可以初步判斷,動(dòng)態(tài)腳本的執(zhí)行時(shí)機(jī)是不確定的,在不同瀏覽器的執(zhí)行時(shí)機(jī)也都存在差異,但總的來看應(yīng)該是在代碼加載結(jié)束之后,并且線程中沒有JavaScript代碼執(zhí)行的某個(gè)時(shí)間,但不同瀏覽器對(duì)這個(gè)時(shí)間有著不同的把握。

因此,動(dòng)態(tài)腳本是否會(huì)阻塞DOMContentLoaded也是不確定的,因?yàn)閯?dòng)態(tài)腳本可能在DOMContentLoaded觸發(fā)之前,也可能在觸發(fā)之后執(zhí)行。而且由于IE<=8不支持真正的DOMContentLoaded事件,jQuery在IE<=8中也是模擬判斷該事件的發(fā)生(下一篇會(huì)專門講解DOMContentLoaded事件),一定程度上也會(huì)對(duì)我們上述代碼的執(zhí)行結(jié)果造成影響。

1.1.3 DEMO3:動(dòng)態(tài)腳本與defer

我們知道,defer腳本是有著相對(duì)明確的執(zhí)行時(shí)機(jī)的,即頁面解析完成之后,DOMContentLoaded觸發(fā)之前加載并且執(zhí)行,事實(shí)上,二者之間在執(zhí)行時(shí)機(jī)上并不存在什么關(guān)聯(lián),但是在實(shí)際實(shí)驗(yàn)中發(fā)現(xiàn),動(dòng)態(tài)腳本可能會(huì)在defer腳本之前或者之后執(zhí)行,但卻不會(huì)打斷defer腳本的執(zhí)行,我們?cè)僖搿稙g覽器環(huán)境下JavaScript腳本加載與執(zhí)行探析之defer與async特性》中2.3節(jié)的DEMO中的defer腳本,修改HTML代碼如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-"/>
<title>Dynamic Script Test</title>
<script src="http://lib.sinaapp.com/js/jquery/../jquery-...min.js"></script>
<script src="util.js"></script>
<script>
$(function(){
test += "我是DOMContentLoaded里面的腳本\n";
})
window.onload = function(){
test += "我是window.onload里面的腳本\n";
var button = document.getElementById("test");
button.onclick = function(){
console.log(test);
}
}
</script>
<script type="text/javascript">var test = "";</script>
<script>
loadScript("dynamic.js");
</script>
<script>
test += "我是head內(nèi)部腳本\n";
</script>
<script src="defer.js" type="text/javascript" defer="defer"></script>
<script src=".js" type="text/javascript"></script>
</head>
<body>
<button id="test">點(diǎn)擊一下</button>
<script>
loadScript("dynamic.js");
</script>
<script src="defer.js" type="text/javascript" defer="defer"></script>
<script src=".js" type="text/javascript"></script>
</body>
<script>
loadScript("dynamic.js");
</script>
<script src="defer.js" type="text/javascript" defer="defer"></script>
<script src=".js" type="text/javascript"></script>
</html> 

注:firefox和opera中執(zhí)行結(jié)果可能會(huì)變化

我們?cè)黾恿藥讉€(gè)defer的腳本,再來看一下各個(gè)瀏覽器中的執(zhí)行結(jié)果:

從實(shí)驗(yàn)結(jié)果可以看出,動(dòng)態(tài)腳本的執(zhí)行時(shí)機(jī)與defer腳本并沒有直接的關(guān)系,表面上看起來在CHROME和firefox中,延遲腳本總是在動(dòng)態(tài)腳本之前執(zhí)行,在《前端優(yōu)化-Javascript篇(2.異步加載腳本)》一文中提到過“ScriptDOM和defer同時(shí)都可以執(zhí)行,在不同瀏覽器中它們的優(yōu)先級(jí)的不一樣的。在Firfox和Chrome中,ScriptDOM的優(yōu)先級(jí)比defer低,而在IE中情況則相反。”,其實(shí)這種優(yōu)先級(jí)應(yīng)該是不存在的,我們只需要將defer腳本加一個(gè)加載延遲,那么動(dòng)態(tài)腳本的執(zhí)行就會(huì)先于defer腳本了。

1.2 動(dòng)態(tài)腳本執(zhí)行問題總結(jié)

我們?cè)賮砜偨Y(jié)一下動(dòng)態(tài)腳本的執(zhí)行問題:

[1]首先,動(dòng)態(tài)腳本確實(shí)能夠在一定程度上起到延遲腳本執(zhí)行的作用,但由于動(dòng)態(tài)腳本的執(zhí)行時(shí)機(jī)的不確定性,這種延遲作用的效果也是未知的。

[2]其次,動(dòng)態(tài)腳本的執(zhí)行順序不一定會(huì)按照添加的順序,這是動(dòng)態(tài)腳本技術(shù)比較大的問題之一,最簡(jiǎn)單的解決方式就是使用回調(diào)函數(shù),監(jiān)聽腳本的加載狀態(tài),在一個(gè)腳本加載結(jié)束后再動(dòng)態(tài)添加下一個(gè)腳本。

[3]動(dòng)態(tài)腳本沒有確切的執(zhí)行時(shí)機(jī),當(dāng)通過DOM的appendChild、insertBefore等方法將script元素添加到DOM中時(shí),就會(huì)去加載JS腳本,腳本的執(zhí)行應(yīng)該是在加載結(jié)束后的某個(gè)時(shí)機(jī),不同瀏覽器對(duì)這個(gè)時(shí)機(jī)的處理差異比較大,比如在IE中,應(yīng)該是采取盡快執(zhí)行的策略,也就是在加載結(jié)束后盡快尋找時(shí)機(jī)執(zhí)行代碼

[4]動(dòng)態(tài)腳本可能會(huì)在DOMContentLoaded觸發(fā)之前或者之后執(zhí)行,因此無法確定其是否會(huì)阻塞DOMContentLoaded。而在一般情況下,動(dòng)態(tài)腳本都會(huì)阻塞window.onload,但是也會(huì)存在動(dòng)態(tài)腳本在window.onload觸發(fā)之后執(zhí)行,從而不會(huì)阻塞window.onload

2 Ajax注入腳本

2.1Ajax注入腳本的執(zhí)行時(shí)機(jī)問題

Ajax腳本注入技術(shù)有兩種模式:同步加載和異步加載,同步加載的情況比較簡(jiǎn)單,腳本的加載和執(zhí)行會(huì)阻塞后面代碼的執(zhí)行,直到注入的代碼被加載和執(zhí)行完畢。我們主要討論異步模式下的情況:

2.1.1 DEMO4:Ajax注入腳本的執(zhí)行問題初探

我們?cè)偬砑?個(gè)外部文件:

ajax1.js

test += "我是head外部AJAX腳本\n";

ajax2.js

test += "我是body外部AJAX腳本\n";

ajax3.js

test += "我是底部外部AJAX腳本\n";

HTML的代碼為:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-"/>
<title>Ajax Script Test</title>
<script src="http://lib.sinaapp.com/js/jquery/../jquery-...min.js"></script>
<script src="util.js"></script>
<script type="text/javascript">var test = "";</script>
<script>
$(function(){
test += "我是DOMContentLoaded里面的腳本\n";
})
window.onload = function(){
test += "我是window.onload里面的腳本\n";
var button = document.getElementById("test");
button.onclick = function(){
console.log(test);
}
}
</script>
<script>
loadXhrScript("ajax.js",true);
</script>
<script>
test += "我是head內(nèi)部腳本\n";
</script>
<script src=".js" type="text/javascript"></script>
</head>
<body>
<button id="test">點(diǎn)擊一下</button>
<script>
loadXhrScript("ajax.js",true);
</script>
<script src=".js" type="text/javascript"></script>
</body>
<script>
loadXhrScript("ajax.js",true);
</script>
<script src=".js" type="text/javascript"></script>
</html> 

在這段代碼中,我們分別在<head>標(biāo)簽內(nèi)部、<body>標(biāo)簽內(nèi)部、<body>標(biāo)簽外部共添加了3個(gè)注入腳本,通過正常引入的腳本作為參照,我們看一下在瀏覽器中的執(zhí)行結(jié)果:

注:firefox、opera、IE中的執(zhí)行結(jié)果可能會(huì)變化

從這個(gè)執(zhí)行結(jié)果中,我們就可以看到,Ajax注入腳本的執(zhí)行時(shí)機(jī)具有更大的不確定性,事實(shí)上,與動(dòng)態(tài)腳本類似,Ajax注入腳本的加載過程也是異步的,因此,完成加載的時(shí)間首先是不確定的,其次,瀏覽器在腳本加載完成后何時(shí)執(zhí)行加載的代碼同樣也是不確定的,對(duì)于異步模式下的Ajax注入腳本的執(zhí)行時(shí)機(jī),我們總結(jié)如下:

[1]Ajax注入的腳本也具有一定的延遲作用,但是與動(dòng)態(tài)腳本類似,延遲的時(shí)間是不確定的。

[2]Ajax注入腳本的執(zhí)行順序是無序的,雖然DEMO4中的例子看起來注入的腳本都是按照添加的順序執(zhí)行的,但是只要稍微理解異步以及動(dòng)態(tài)腳本執(zhí)行順序問題,就應(yīng)該能夠明白這一點(diǎn)。

[3]Ajax注入腳本的執(zhí)行時(shí)機(jī)也是不確定的,與腳本的加載時(shí)間以及瀏覽器的處理機(jī)制有關(guān)。

[4]由于上述的幾點(diǎn),Ajax注入的腳本可能會(huì)阻塞DOMContentLoaded,也可能會(huì)阻塞window.onload。

相關(guān)文章

  • js實(shí)現(xiàn)選項(xiàng)卡效果

    js實(shí)現(xiàn)選項(xiàng)卡效果

    這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)選項(xiàng)卡效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • IE與Firefox在JavaScript上的7個(gè)不同句法分享

    IE與Firefox在JavaScript上的7個(gè)不同句法分享

    盡管那需要用長(zhǎng)串的、沉悶的不同分支代碼來應(yīng)付不同瀏覽器的日子已經(jīng)過去,偶爾還是有必要做一些簡(jiǎn)單的區(qū)分和目標(biāo)檢測(cè)來確保某塊代碼能在用戶的機(jī)器上正常運(yùn)行
    2011-10-10
  • js中javascript:void(0) 真正含義

    js中javascript:void(0) 真正含義

    在javascript中javascript:void(0)經(jīng)常會(huì)用到,大家知道此含有嗎,在Javascript中void是一個(gè)操作符,該操作符指定要計(jì)算一個(gè)表達(dá)式但是不返回值,本文給大家介紹js中javascript:void(0) 真正含義,需要的朋友可以參考下
    2015-08-08
  • js提示框替代系統(tǒng)alert,自動(dòng)關(guān)閉alert對(duì)話框的實(shí)現(xiàn)方法

    js提示框替代系統(tǒng)alert,自動(dòng)關(guān)閉alert對(duì)話框的實(shí)現(xiàn)方法

    下面小編就為大家?guī)硪黄猨s提示框替代系統(tǒng)alert,自動(dòng)關(guān)閉alert對(duì)話框的實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-11-11
  • 特想搞點(diǎn)新的創(chuàng)意出來-立體方塊

    特想搞點(diǎn)新的創(chuàng)意出來-立體方塊

    特想搞點(diǎn)新的創(chuàng)意出來-立體方塊...
    2007-06-06
  • JavaScript canvas實(shí)現(xiàn)代碼雨效果

    JavaScript canvas實(shí)現(xiàn)代碼雨效果

    這篇文章主要為大家詳細(xì)介紹了JavaScript canvas實(shí)現(xiàn)代碼雨效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • js判斷樣式className同時(shí)增加class或刪除class

    js判斷樣式className同時(shí)增加class或刪除class

    用正則表達(dá)式判斷多個(gè)class之間是否存在真正的class(前后空格的處理)然后增加class刪除class,本文給予實(shí)現(xiàn)方法,感興趣的朋友可以了解下,或許對(duì)你有所幫助
    2013-01-01
  • 再論Javascript的類繼承

    再論Javascript的類繼承

    說到Javascript的類繼承,就必然離不開原型鏈,但只通過原型鏈實(shí)現(xiàn)的繼承有著不少缺陷。
    2011-03-03
  • js判斷輸入字符串是否為空、空格、null的方法總結(jié)

    js判斷輸入字符串是否為空、空格、null的方法總結(jié)

    下面小編就為大家?guī)硪黄猨s判斷輸入字符串是否為空、空格、null的方法總結(jié)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-06-06
  • javascript實(shí)現(xiàn)發(fā)送短信驗(yàn)證碼案例

    javascript實(shí)現(xiàn)發(fā)送短信驗(yàn)證碼案例

    這篇文章主要為大家詳細(xì)介紹了javascript實(shí)現(xiàn)發(fā)送短信驗(yàn)證碼案例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-07-07

最新評(píng)論