按照任務(wù)中的代碼睦刃,在IE8下提示:對象不支持“addEventListener”屬性或方法搬俊。
在Chrome下缩擂,是字符串拼接滤港。
了解JavaScript是什么
JavaScript 是一種跨平臺廊蜒,面向?qū)ο蟮哪_本語言。作為一種小巧且輕量級的語言溅漾,JavaScript 無意于獨(dú)立運(yùn)行山叮,而是被設(shè)計(jì)為可以輕易嵌入到其它的產(chǎn)品和應(yīng)用中,比如 Web 瀏覽器添履。在宿主環(huán)境中屁倔,JavaScript 可以被連接到環(huán)境中的對象之上,以提供對其的編程控制暮胧。
核心的 JavaScript 中包含有一組核心的對象锐借,包括 Array问麸,Date 和 Math,以及一組核心的語言要素钞翔,包括操作符严卖,控制結(jié)構(gòu)和語句。出于多種目的布轿,可以通過為其增補(bǔ)附加的對象哮笆,對核心 JavaScript 加以擴(kuò)展;例如:
客戶端 JavaScript 提供了用于控制瀏覽器(Navigator 或者其它瀏覽器)以及其中的文檔對象模型(DOM)的對象汰扭,從而擴(kuò)展了核心 JavaScript稠肘。例如,客戶端擴(kuò)展允許應(yīng)用程序在 HTML 的表單中加入元素萝毛,以便響應(yīng)用戶事件项阴,比如鼠標(biāo)點(diǎn)擊,表單輸入和頁面導(dǎo)航笆包。
服務(wù)器端 JavaScript 提供了服務(wù)于在服務(wù)器上運(yùn)行 JavaScript 的對象环揽,從而擴(kuò)展了核心 JavaScript。例如色查,服務(wù)器端擴(kuò)展可以允許應(yīng)用程序訪問關(guān)系型數(shù)據(jù)庫薯演,在應(yīng)用程序的不同調(diào)用間提供信息的連續(xù)性,甚至于處理服務(wù)器之上的文件秧了。
借由 JavaScript 的 LiveConnect 功能跨扮,您可以讓 Java 和 JavaScript 間實(shí)現(xiàn)通訊。從 JavaScript 中验毡,您可以創(chuàng)建 Java 對象并訪問它們的公共方法和域衡创。從 Java 中,也可以訪問 JavaScript 的對象晶通,屬性和方法璃氢。
Netscape 發(fā)明了 JavaScript 并將 JavaScript 首先用于 Netscape 瀏覽器中。
如何在HTML頁面加載JavaScript代碼
使用<script>標(biāo)簽在 HTML 文件中添加 JavaScript 代碼狮辽。
我們可以將JavaScript代碼放在html文件中任何位置一也,但是我們一般放在網(wǎng)頁的head或者body部分。
放在<head>部分
最常用的方式是在頁面中head部分放置<script>元素喉脖,瀏覽器解析head部分就會執(zhí)行這個(gè)代碼椰苟,然后才解析頁面的其余部分。
放在<body>部分
JavaScript 代碼在網(wǎng)頁讀取到該語句的時(shí)候就會執(zhí)行树叽。
注意: javascript 作為一種腳本語言可以放在 html 頁面中任何位置沪悲,但是瀏覽器解釋 html 時(shí)是按先后順序的影所,所以前面的 script 就先被執(zhí)行丽柿。比如進(jìn)行頁面顯示初始化的 js 必須放在 head 里面,因?yàn)槌跏蓟家筇崆斑M(jìn)行(如給頁面 body 設(shè)置 css 等)寒随;而如果是通過事件調(diào)用執(zhí)行的 function 那么對位置沒什么要求的。
為什么要把<script>放在</body>前
理論上放在哪里都是可以的,但是對于前端頁面優(yōu)化來講,還是放在底部是最佳的叫胖,因?yàn)槿绻鸍S執(zhí)行出現(xiàn)錯(cuò)誤了,最起碼頁面中的元素還能加載出來她奥,因?yàn)镈OM文檔是從上往下的順序執(zhí)行的臭家。
按照HTML5標(biāo)準(zhǔn)中的HTML語法規(guī)則,如果在</body>后再出現(xiàn)<script>或任何元素的開始標(biāo)簽方淤,都是parse error,瀏覽器會忽略之前的</body>蹄殃,即視作仍舊在body內(nèi)携茂。所以實(shí)際效果和寫在</body>之前是沒有區(qū)別的。
JavaScript 的性能優(yōu)化:加載和執(zhí)行
腳本位置
由于腳本會阻塞頁面其他資源的下載诅岩,因此推薦將所有<script>標(biāo)簽盡可能放到<body>標(biāo)簽的底部讳苦,以盡量減少對整個(gè)頁面下載的影響。
組織腳本
由于每個(gè)<script>標(biāo)簽初始下載時(shí)都會阻塞頁面渲染吩谦,所以減少頁面包含的<script>標(biāo)簽數(shù)量有助于改善這一情況鸳谜。這不僅針對外鏈腳本,內(nèi)嵌腳本的數(shù)量同樣也要限制式廷。瀏覽器在解析 HTML 頁面的過程中每遇到一個(gè)<script>標(biāo)簽咐扭,都會因執(zhí)行腳本而導(dǎo)致一定的延時(shí),因此最小化延遲時(shí)間將會明顯改善頁面的總體性能滑废。
無阻塞的腳本
減少 JavaScript 文件大小并限制 HTTP 請求數(shù)在功能豐富的 Web 應(yīng)用或大型網(wǎng)站上并不總是可行蝗肪。Web 應(yīng)用的功能越豐富,所需要的 JavaScript 代碼就越多蠕趁,盡管下載單個(gè)較大的 JavaScript 文件只產(chǎn)生一次 HTTP 請求薛闪,卻會鎖死瀏覽器的一大段時(shí)間。為避免這種情況俺陋,需要通過一些特定的技術(shù)向頁面中逐步加載 JavaScript 文件豁延,這樣做在某種程度上來說不會阻塞瀏覽器。
無阻塞腳本的秘訣在于腊状,在頁面加載完成后才加載 JavaScript 代碼诱咏。這就意味著在 window 對象的 onload事件觸發(fā)后再下載腳本。有多種方式可以實(shí)現(xiàn)這一效果寿酌。
標(biāo)簽盡可能放到標(biāo)簽的底部胰苏,以盡量減少對整個(gè)頁面下載的影響。
或任何元素的開始標(biāo)簽,都是parse error硕并,瀏覽器會忽略之前的法焰,即視作仍舊在body內(nèi)。所以實(shí)際效果和寫在之前是沒有區(qū)別的倔毙。
標(biāo)簽在 HTML 文件中添加 JavaScript 代碼埃仪。
標(biāo)簽在 HTML 文件中添加 JavaScript 代碼。
??? ·延遲加載腳本
HTML 4 為<script>標(biāo)簽定義了一個(gè)擴(kuò)展屬性:defer陕赃。Defer 屬性指明本元素所含的腳本不會修改 DOM卵蛉,因此代碼能安全地延遲執(zhí)行。
帶有 defer 屬性的<script>標(biāo)簽可以放置在文檔的任何位置么库。對應(yīng)的 JavaScript 文件將在頁面解析到<script>標(biāo)簽時(shí)開始下載傻丝,但不會執(zhí)行,直到 DOM 加載完成诉儒,即onload事件觸發(fā)前才會被執(zhí)行葡缰。當(dāng)一個(gè)帶有 defer 屬性的 JavaScript 文件下載時(shí),它不會阻塞瀏覽器的其他進(jìn)程忱反,因此這類文件可以與其他資源文件一起并行下載泛释。
HTML 5 為<script>標(biāo)簽定義了一個(gè)新的擴(kuò)展屬性:async。它的作用和 defer 一樣温算,能夠異步地加載和執(zhí)行腳本怜校,不因?yàn)榧虞d腳本而阻塞頁面的加載。但是有一點(diǎn)需要注意注竿,在有 async 的情況下茄茁,JavaScript 腳本一旦下載好了就會執(zhí)行,所以很有可能不是按照原本的順序來執(zhí)行的蔓搞。如果 JavaScript 腳本前后有依賴性胰丁,使用 async 就很有可能出現(xiàn)錯(cuò)誤。
IE8,9不支持async
??? ·動(dòng)態(tài)腳本元素
function loadScript(url, callback){
??? var script = document.createElement ("script")
??? script.type = "text/javascript";
??? if (script.readyState){ //IE
??????? script.onreadystatechange = function(){
??????????? if (script.readyState == "loaded" || script.readyState == "complete"){
??????????????? script.onreadystatechange = null;
??????????????? callback();
??????????? }
??????? };
??? } else { //Others
??????? script.onload = function(){
?????? ? ?? callback();
?? ? ?? };
??? }
??? script.src = url;
??? document.getElementsByTagName("head")[0].appendChild(script);
}
此函數(shù)接收兩個(gè)參數(shù):JavaScript 文件的 URL喂分,和一個(gè)當(dāng) JavaScript 接收完成時(shí)觸發(fā)的回調(diào)函數(shù)锦庸。屬性檢查用于決定監(jiān)視哪種事件。最后一步蒲祈,設(shè)置src屬性甘萧,并將<script>元素添加至頁面。
loadScript("script1.js", function(){
??? alert("File is loaded!");
});
動(dòng)態(tài)腳本加載是非阻塞 JavaScript 下載中最常用的模式梆掸,因?yàn)樗梢钥鐬g覽器扬卷,而且簡單易用。
??? ·使用 XMLHttpRequest(XHR)對象
var xhr = new XMLHttpRequest();
xhr.open("get", "script1.js", true);
xhr.onreadystatechange = function(){
??? if (xhr.readyState == 4){
???????? if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
??????????? var script = document.createElement ("script");
??????????? script.type = "text/javascript";
??????????? script.text = xhr.responseText;
?????????? document.body.appendChild(script);
??????? }
??? }
}酸钦;
xhr.send(null);
元素添加至頁面怪得。
這種方法的主要優(yōu)點(diǎn)是,您可以下載不立即執(zhí)行的 JavaScript 代碼。由于代碼返回在<script>標(biāo)簽之外(換句話說不受<script>標(biāo)簽約束)徒恋,它下載后不會自動(dòng)執(zhí)行蚕断,這使得您可以推遲執(zhí)行,直到一切都準(zhǔn)備好了入挣。另一個(gè)優(yōu)點(diǎn)是亿乳,同樣的代碼在所有現(xiàn)代瀏覽器中都不會引發(fā)異常。
此方法最主要的限制是:JavaScript 文件必須與頁面放置在同一個(gè)域內(nèi)径筏,不能從 CDN 下載(CDN 指"內(nèi)容投遞網(wǎng)絡(luò)(Content Delivery Network)"葛假,所以大型網(wǎng)頁通常不采用 XHR 腳本注入技術(shù)。
總結(jié)
減少 JavaScript 對性能的影響有以下幾種方法:
將所有的<script>標(biāo)簽放到頁面底部滋恬,也就是</body>閉合標(biāo)簽之前聊训,這能確保在腳本執(zhí)行前頁面已經(jīng)完成了渲染。
盡可能地合并腳本恢氯。頁面中的<script>標(biāo)簽越少魔眨,加載也就越快,響應(yīng)也越迅速酿雪。無論是外鏈腳本還是內(nèi)嵌腳本都是如此。
采用無阻塞下載 JavaScript 腳本的方法:
? ? 使用<script>標(biāo)簽的 defer 屬性
??? 使用動(dòng)態(tài)創(chuàng)建的<script>元素來下載并執(zhí)行代碼侄刽;元素來下載并執(zhí)行代碼指黎;
??? 使用 XHR 對象下載 JavaScript 代碼并注入頁面中。
通過以上策略州丹,可以在很大程度上提高那些需要使用大量 JavaScript 的 Web 網(wǎng)站和應(yīng)用的實(shí)際性能醋安。