平穩退化
如果正確的使用了JavaScript腳本,就可以讓訪問者在他們的瀏覽器不支持JavaScript的情況下仍能順利地瀏覽網站。這就是平穩退化,即雖然某些功能無法使用,但最基本的操作仍能順利完成。
平穩退化的經典例子:(比較以下幾條語句)
1 <a href="javascript:popUp('http://www.example.com/');">Example</a> 2 <a href="#" onclick="popUp('http://www.example.com/');return false;">Example1</a> 3 <a href="http://www.example.com/" onclick="popUp('http://www.example.com/');return false;">Example2</a> 4 <a href="http://www.example.com/" onclick="popUp(this.getAttribute('href'));return false;">Example3</a> 5 <a href="http://www.example.com/" onclick="popUp(this.href);return false;">Example4</a>
在把href屬性設置為真是存在的URL地址后,即使javascript已被禁用,這個鏈接也是可用的。雖然這個鏈接沒有打開一個新窗口,但它沒有徹底失效。這就是一個經典的平穩退化的例子。
window.open()創建新的瀏覽器窗口
語法:window.open(url,name,features)
第一個參數:想在新瀏覽器窗口里打開的網頁地址。(如果省略這個參數,屏幕上將彈出一個空白的瀏覽器窗口)
第二個參數:新窗口的名字。(代碼里可以通過這個名字與新窗口進行通信)
第三個參數:新窗口的各種屬性,以逗號分隔的字符串。(屬性包括新窗口的尺寸以及新窗口被啟用或禁用的各種瀏覽器功能(工具條,菜單條,初始位置等))
"javascript:"偽協議
“真”協議用來在因特爾上的計算機之間傳輸數據包,如http協議,ftp協議等。
偽協議是一種非標准化的協議。
“javascript:”偽協議讓我們通過一個鏈接來調用JavaScript函數。
例如:
<a href="javascript:popUp('http://www.example.com/');">Example</a>
這條語句在支持“javascript:”偽協議的瀏覽器中運行正常,較老的瀏覽器會嘗試打開鏈接但失敗,支持這種為協議但是禁用了javascript功能的瀏覽器什么也不做。
結構與樣式的分離
文檔結構與樣式的分離可以確保網頁都能平穩退化。
漸進增強
所謂漸進增強就是用一些額外的信息層去包裹原始數據。按照漸進增強原則創建出來的網頁幾乎都符合平穩退化原則。
類似於CSS,JavaScript和DOM提供的所有功也應該構成一個額外的指令層。CSS代碼負責提供關於“表示”的信息,JavaScript負責提供關於“行為”的信息。行為層的應用方式與表示層一樣。
分離JavaScript
在JS文件里把一個事件添加到某個元素上
語法:element.event = action
例如:想把一個事件添加到某個帶有特定id屬性的元素上:getElementById(“idName”).event = action
在JS文件里把一個事件添加到有特定屬性的一組元素上(如所有的class=“popup”的a標簽)
具體步驟:把文檔里所有的鏈接全放入一個數組中——>遍歷數組——>如果某個鏈接的class屬性等於popup,就把這個鏈接的href屬性值傳給popUp函數——>並取消這個鏈接的默認行為,不讓這個鏈接把訪問者帶離當前窗口。(return false即可)
例如:
1 function prepareLinks(){ 2 var links = document.getElementsByTagName("a"); 3 for(var i = 0; i < links.length; i++){ 4 if(links[i].getAttribute("calss") === "popup"){ 5 //匿名函數 6 links[i].onclick = function(){ 7 popUp(this.getAttribute("href")); 8 return false; 9 } 10 } 11 } 12 }
window.onload()事件——HTML文檔全部加載完觸發的事件
必須讓上面的給a標簽添加事件的代碼在HTML文檔全部加載到瀏覽器后馬上開始執行。
HTML文檔全部加載完畢時將觸發一個事件,這個時間有自己的事件處理函數。
文檔被加載到瀏覽器窗口里,document對象又是window對象的一個屬性。當window對象觸發onload事件時,document對象已經存在。
所以可以這樣添加上面的函數到window對象的onload事件上去,如下所示:
window.onload = prepareLinks;
向后兼容
對象檢測
只要把某個方法打包在一個if語句里,就可以根據這個語句的條件表達式的求求值結果是true(這個方法存在)還是false(這個方法不存在)來決定采取怎樣的行動。這種檢測叫做對象檢測。
語法:if(method){ statement }
注意:在對象檢測時一定要刪掉方法名后面的圓括號,不刪掉的話,測試的將是方法的結果,無論方法是否存在。
使用對象檢測是為了讓腳本有良好的向后兼容性,確保“古老”的瀏覽器不會因為腳本代碼而出現問題。
遵循漸進增強的原則,可以確切的知道添加的事件都能平穩退化,網頁在老版本的瀏覽器中也能正常瀏覽,那些只支持一部分JavaScript功能但不支持DOM的瀏覽器仍然可以訪問網頁的內容。
瀏覽器嗅探技術
瀏覽器嗅探指的是通過提取瀏覽器供應商提供的信息來解決向后兼容問題。
理論上講,可以通過JavaScript代碼檢索關於瀏覽器品牌和版本信息,這些信息可以用來改善JavaScript腳本代碼的向后兼容性,但是這是一項風險較大的技術。
首先,有些瀏覽器會把自己報告為另一種瀏覽器,還有一些瀏覽器允許用戶任意修改這些信息。
其次,為了適應多種不同的瀏覽器,要讓瀏覽器嗅探腳本跨平台工作,就必須測試所有可能出現的供應商和版本號的組合。測試的組合情況非常多,腳本代碼冗長復雜。
性能考慮
盡量減少訪問DOM和盡量減少標記
不管什么時候,只要是查詢DOM中的某些元素,瀏覽器都會搜索整個DOM書,從中查找可能匹配的元素。更好的辦法是把第一次搜索到的結果保存在一個變量中,然后在循環里重用這個結果。
盡量減少文檔中的標記數量,過多不必要的元素只會增加DOM樹的規模,進而增加遍歷DOM樹以查找特定元素的時間。
合並並放置腳本
合並腳本可以減少加載頁面時發送請求的數量,而減少發送請求的數量通常是性能優化時首先要考慮的。
腳本在標記中的位置對頁面初次加載時間也有很大的影響。位於head塊中的腳本會導致瀏覽器無法並行加載其他文件(如圖像或其他腳本)。
根據http規范,瀏覽器每次從同一域名中最多只能同時下載兩個文件。而在下載腳本呢期間,瀏覽器不會下載其它文件,即使是來自同一域名的文件。所有其他資源必須等腳本加載完畢后才能加載。
把所有script腳本放在文檔的末尾,</body>標簽的前面,就可以讓頁面變得更快。
這樣,在加載腳本時,window對象的load事件依然可以執行對文檔進行的各種操作。
壓縮腳本
壓縮腳本指的是把腳本中不必要的字節,如空格和注釋統統刪除。使用代碼壓縮工具可以達到這個目的,有的甚至會重寫你得部分代碼,使用更短的變量名,從而減少整體文件的大小。
代碼壓縮工具有:JSMin(Douglas Crockford)、YUI Compressor(雅虎)、Closure Compiler(谷歌)
JS添加行為的一個重要准則
不應該讓JavaScript代碼對這個網頁的結構有任何的依賴。
結構化程序設計
結構化程序設計中有一條原則是:函數應該只有一個入口和一個出口。
如果一個函數有多個出口,只要這個出口集中出現在函數的開頭部分,也是可以接受的。
匿名函數
定義匿名函數是一種可以在代碼執行時創建函數的辦法。
共享onload事件
每個事件處理函數只能綁定一條指令。當有不止一個函數主要在網頁加載完畢后立刻執行時,需要共享onload事件。此時有兩種方法可以共享onload事件。
1.先創建一個匿名函數來容納這幾個要執行的函數,然后把該匿名函數綁定在onload事件上。如:
window.onload = function(){ firstFunction(); secondFunction(); }
2.彈性最佳解決方案:把那些在頁面加載完成后要立刻執行的函數創建為一個隊列。addLoadEvent函數就是一種選擇,它只有一個參數:打算在頁面加載完畢時執行的函數名。
這個函數完成的操作是:首先,把現有的window.onload事件處理函數的值存入變量oldonload;然后判斷,如果在這個處理函數上還沒有綁定任何函數,則把新函數添加給它;如果在這個處理函數上已經綁定了一些函數,那么就把新函數追加到現有指令的末尾。代碼清單如下:
1 function addLoadEvent(func){ 2 var oldonload = window.onload; 3 if(typeof window.onload != 'function'){ 4 window.onload = func; 5 } else { 6 window.onload = function(){ 7 oldonload(); 8 func(); 9 } 10 } 11 }
在使用時只要寫出以下代碼即可:addLoadEvent(firstFunction);addLoadEvent(secondFunction)
三元操作符
if/else語句的一種變體形式。
語法:variable = condition ? if true : if false;
表示在條件成立時,變量被賦值為第一個表達式,如果條件不成立,變量就賦值為第二個表達式。
nodeName屬性
返回節點的名字,而且返回的值總是顯示為大寫字母,即使在html文檔里是小寫字母。
例如:if (placeholder.nodeName != "IMG") return false; 表示如果placeholder不是img標簽的話返回false。
onkeypress事件
onkeypress事件處理函數是專門來處理鍵盤事件的。按下鍵盤上的任何一個按鍵都會觸發這個onkeypress事件。
想讓onkeypress事件與onclick事件觸發同樣的行為,可以把有關的指令復制一遍,也可以用node.onclick = node.onkeypress代碼實現。
注意:onkeypress事件處理函數很容易出現的問題是用戶每按下一個鍵都會觸發它,在某些瀏覽器中甚至包括Tab鍵,這意味着如果綁定在onkeypress時間上的處理函數上返回的是false,那些只使用鍵盤訪問的用戶將永遠無法離開當前連接。
不過,在幾乎所有的瀏覽器中,用Tab鍵移動到某個鏈接然后按下回車鍵的動作也會觸發onclick事件。
onclick事件處理函數已經能滿足需要的情況下,最好不使用onkeypress事件處理函數。
DOM Core 和 HTML-DOM
getElementById、getElementsByTagName、getAttribute、setAttribute等方法都是DOM Core的組成部分。它們並不專屬於JavaScript,支持DOM的任何一種程序設計語言都可以使用。它們的用途也並非僅限於處理網頁,可以用來處理任何一種標記語言(如XML)編寫出來的文檔。
相應的也有HTML_DOM可以使用。
例如:
document.getElementsByTagName("form")等價於document.form
element.getAttribute("src")等價於element.src
這樣,在代碼編寫過程中,有些地方就可以使用HTML-DOM來簡化代碼。
然后……繼續准備明后天的考試去了……
fighting!O(∩_∩)O~