Script標籤
script標籤用於在HTML頁面中嵌入一些可執的指令碼
<script> //some script goes here </script>
script標籤有三個特殊的屬性(當然,像id,class這樣的屬性它也是有的,HTML頁面中幾乎每個元素都可以有class,id屬性)
<script language="JavaScript">//language屬性指明標籤裡包含的指令碼所使用的語言 //它有三個常見的取值JavaScript,JScript,VBScript //some script goes here </script> //對於JScript只有IE能夠識別,其它瀏覽器會忽略這個標籤其裡面的內容 //而對於VBScript,只有Windows上的IE能夠識別,執行 //然而language屬性後來在XHTML中被type屬性替代了 <script type="text/javascript">//取值也變了,text/javascript,text/jscript,text/vbscript //some script goes here </script>
在Web瀏覽器中,我們只會使用JavaScript,type屬性設定為text/javascript.事實上,由於JavaScript十分流行,它幾乎成了指令碼的代名詞,而在Web瀏覽器中,即使script標籤不加任何屬性,瀏覽器也會把它當成JavaScript
<script> alert("Hello!"); </script> //上面的那段程式碼將會按JavaScript的方式執行 //即使有IE中,不加宣告的script塊也會當成JavaScript執行,而不是VBScript <script> msgbox "Hello!" </script> //上面的程式碼在IE中也會報錯,IE也會將其當成JavaScript執行
以前在HTML頁面中,一些標籤常會加一些諸如onclick,onmouseover這樣的屬性,這是一種事件繫結(關於事件,我們之後會詳細講解的,不要急).用於指定當HTML頁面某個元素上發生了什麼事的時候去執行的JavaScript程式碼(當然也可以是其它客戶端指令碼)
<img src="../images/stack_heap.jpg" alt="記憶體堆疊" onclick="alert('你把我點疼了!')" />
上面的程式碼將在HTML頁面上顯示一個影象,當你用滑鼠點選一下時,會出現一個彈窗,顯示'你把我點疼了!',onclick屬性的值其實是一段JavaScript程式碼;這就是事件,下面是其它一些簡單的事件
- onclick ,當滑鼠點選一下時執行一次
- onmouseover ,當滑鼠放上去時執行一次
- onmouseout ,當滑鼠移出去時執行一次
- onmousedown ,當滑鼠按下時執行一次
- onmouseup ,當滑鼠在上面鬆開(彈起)時執行一次
- onmousedblclick ,當滑鼠雙擊時執行一次
- onload ,當物件載入完成時執行一次
以前網上十分流行的稱之為RollverImages(翻轉影象)的效果其實就是組合onmouseover,onmouseout這樣的事件和簡單的JavaScript程式碼實現的
<img src="../images/stack_heap.jpg" alt="記憶體堆疊" onmouseover="this.src='../images/over.jpg'" onmouseout="this.src='../images/out.jpg'" />
你可能知道,onmouseover這類的屬性中的字串將會在事件發生時當成指令碼來執行,但上面的那些程式碼看上去十分模糊
//為了便於檢視,我們將它們提取出來放在下面 this.src='../images/over.jpg' this.src='../images/out.jpg'
分析上面的程式碼,我們發現,這其實是在給一個物件this的屬性src賦值,但問題是我們並沒有宣告過一個叫this的物件!其實this物件是一個一直存在的一個物件,它不能被宣告(this是關鍵字).這裡,this就是指"這個",指這個標籤!對於HTML中的元素,JavaScript會自動將其解析成一個物件.對於下面的img標籤,會解析成下面一個物件:
<img src="../images/stack_heap.jpg" alt="記憶體堆疊" onclick="alert('Hello!')" /> //注意,實際上this是不能手動賦值,也不能手動宣告的,這裡僅僅是演示 this = { src:"../images/stack_heap.jpg", alt:"記憶體堆疊", onclick:"alert('Hello!')", tagName:"IMG" }; //其實不止這些屬性
上面,img標籤會被解析成一個物件,具有src,alt等屬性,src,alt屬性是我們寫在HTML裡面的,而tagName則是系統自動生成的,它表示標籤的標籤名!我們可以用下面的程式碼進行測試:
<img src="../images/stack_heap.jpg" alt="記憶體堆疊" onclick="alert(this.src);alert(this.tagName);" />
自然,我們也可以修改它的值,於是翻轉圖象的效果就這樣成功了
對於這樣的行內事件繫結,有一些注意點.
<head> <script> function myFn() { alert("圖象載入完成了!"); } </script> </head> //.............若干若干程式碼之後 <img src="../images/stack_heap.jpg" alt="記憶體堆疊" onload="myFn()" />//當圖象載入成功時執行一個函式
上面的程式碼執行是沒問題的,然而將順序翻轉一下(script可以放在任何合法的地方)
<img src="../images/stack_heap.jpg" alt="記憶體堆疊" onload="myFn()" />//當圖象載入成功時執行一個函式 //.............若干若干程式碼之後 <script> function myFn() { alert("圖象載入完成了!"); } </script>
HTML頁面按照從上往下的順序載入執行,當圖象載入成功後,就去執行onload裡的內容(一個自定義函式),但由於script標籤在下面若干程式碼之後,所以還沒被載入,因此會出錯"myFn is undefined";這就是為什麼要將script標籤放在head部分的原因,因為head在body前面,當body裡的元素載入完成時,head中的script肯定載入完成了
但後來有了XHTML,有了"三層分離",W3C推出了DOM2,我們需要使用另一種方式繫結事件,獲取HTML頁面元素.再以上面的影象為例:
<head> <script> var img = document.getElementById("myImg");//我們通過ID來獲取它 //document.getElementById方法有個引數,一個字串ID //然後,img就表示了那個影象標籤物件 img.onclick = myFn; /*我們不是把JavaScript程式碼以字串符值給它的onclick屬性 而是直接賦值給它一個函式名 你也會說,為什麼不是img.onclick=myFn(); 因為現在是在JavaScript程式碼區域中 加"()"表示執行這個函式,然後將這個函式的返回值賦給了img.onclick*/ function myFn() { alert("圖象載入完成了!"); } </script> </head> //....... <img src="../images/stack_heap.jpg" id="myImg" alt="記憶體堆疊" /> //我們不再加onclick屬性了,而是給它起了個ID
但上面的程式碼執行了仍會出錯,因為HTML從上往下載入,當載入到script時,body部分在下面,還沒有被載入,而JavaScript在瀏覽載入到時就會自動執行.這時,頁面上的ID為myImg的img還沒被載入到,所以會出錯;document.getElementById方法需要一個字串形式的ID,而如果頁面上沒有ID為這個的元素,它則會返回null(空物件);而在下面一行,img.onclick這一句使用了一個空物件,所以會在這裡出錯!至於解決方法,其實只是將傳統的行內事件繫結的script位置反過來放.將script放在所以HTML元素後面!
<img src="../images/stack_heap.jpg" id="myImg" alt="記憶體堆疊" /> //..................若干程式碼之後 <script> var img = document.getElementById("myImg"); //這個時候,由於script標籤放置的位置處在img標籤之後,載入到script時img標籤肯定載入完成了 img.onclick = myFn; function myFn() { alert("圖象載入完成了!"); } </script>
但標準仍然推薦將script放在head部分!那麼,這就要用到另一個事件onload
window.onload = initAll;//將所有程式碼寫在一個函式之中,然後註冊到window物件的onload事件屬性上 //window表示視窗物件,只要視窗開啟,它就始終存在,當頁面載入完成後,會觸發window物件上的onload事件 function initAll() { var img = document.getElementById("myImg"); img.onclick = myFn; function myFn() { alert("圖象載入完成了!"); } }
這樣,程式碼就不出錯了,不管將指令碼放在什麼位置,initAll只有當頁面載入完成後才會被執行
訪問HTML頁面:HTML DOM
HTML DOM將整個頁面當成一個document物件,HTML裡的標籤都要通過document物件來訪問.而文件中的每個標籤,又會轉換成一個物件
<p class="demo" title="第一個段落:DOM樹" id="p1">我們用一個p標籤來演示</p>
它又會被轉換成下面這個物件
//總該記得物件字面量語法吧 { tagName:"p", className:"demo", title:"第一個段落:DOM樹", id:"p1", innerHTML:"我們用一個p標籤來演示" } //你也許會奇怪,為什麼標籤的class屬性會變成物件的className屬性而不是class. //class是JavaScript保留字!!! //tagName表示它的標籤名,而innerHTML表示它裡面的HTML程式碼
瀏覽將HTML標籤轉換成這樣的物件後,在JavaScript中訪問該標籤的屬性或裡面的內容就簡單多了,但問題是如何訪問到這個物件!!
//首先要給該標籤加個ID,然後使用document.getElementById方法就能夠訪問到它了 window.onload = initAll;//注意,要將所要訪問HTML頁面的程式碼都放在window的onload事件處理上! function initAll() { var p = document.getElementById("p1"); alert(p.className); alert(p.tagName); alert(p.title); alert(p.id); alert(p.innerHTML); }
訪問HTML頁面就這麼簡單!獲取一個元素之後,不但可以讀取它的屬性值,還可以設定它的屬性值!
window.onload = initAll; function initAll() { var p = document.getElementById("p1"); p.title="JavaScript"; p.className="load";//我們可以更改它的樣式 }
利用這些,我們已經能做出一些激動人心的事了!
//一些CSS .over { color:red; background:blue; font-size:larger; } .out { color:black; background:white; font-size:smaller; } .click { color:yellow; background:yellow; font-size:12px; }
//HTML程式碼 <p id="p1" class="out">一大行文字,它們都是普通的文字!</p>
//JavaScript程式碼 window.onload = initAll; function initAll() { var p = document.getElementById("p1"); p.onclick=clickFn;//這裡的事件註冊方式除了比行內註冊方式少了括號,其它的是一樣的 p.onmouseover = overFn; p.onmouseout = outFn; } function clickFn() { this.className="click";//這裡,this也是可用的 //注意是className,而不是class } function overFn() { this.className="over"; } function outFn() { this.className="out"; }
當然,獲取頁面元素不止這一種方法.document.getElementsByTagName方法也能獲取頁面元素,顧名思意,它是通過HTML的標籤來獲取元素的,而不是ID. 因為一張HTML頁面,一個ID名稱是唯一的,而標籤名則大多數是相同的,所以,getElementsByTagName方法只有一個引數,即一個字串形式的標籤名(tagName),而返回值則是一個類似陣列的HTML元素列表
window.onload = initAll;//仍然要寫在window.onload事件處理函式中 function initAll() { var pList = document.getElementsByTagName("P"); //為什麼要用大寫的P?其實用小寫p也可以,不區分大小寫,但由於物件的tagName總報告的是大寫的,就.... alert(pList.length);//與陣列相似,length報告有多少個元素,頁面上有多少個p標籤,就報告多少 alert(pList[0].innerHTML);//這樣來訪問第一個p元素 }
另外,對於document.getElementsByTagName方法,還可以傳一個"*"號作為引數,以獲取頁面的所有元素,類似於CSS裡面的萬用字元
window.onload = initAll; function initAll() { var allThings = document.body.getElementsByTagName("*"); //可在任何DOM元素上呼叫getElementsByTagName方法,在body上呼叫此方法時,body外的標籤不會獲取到 alert(allThings.length);//頁面上有多少個標籤,就報告多少(包含DOCTYPE) alert(allThings[3].innerHTML);//這樣來訪問第四個元素 }
其它-javascript:偽協議
偽協議不同於因特網上所真實存在的如http://,https://,ftp://,而是為關聯應用程式而使用的.如:tencent://(關聯QQ),data:(用base64編碼來在瀏覽器端輸出二進位制檔案),還有就是javascript:
我們可以在瀏覽位址列裡輸入"javascript:alert('JS!');",點轉到後會發現,實際上是把javascript:後面的程式碼當JavaScript來執行,並將結果值返回給當前頁面
類似,我們可以在a標籤的href屬性中使用javascript偽協議
<a href="javascript:alert('JS!');"></a> //點選這面的連結,瀏覽器並不會跳轉到任何頁面,而是顯示一個彈窗
但javascript:偽協議有個問題,它會將執行結果返回給當然的頁面
<a href="javascript:window.prompt('輸入內容將替換當前頁面!','');">A</a>
解決方法很簡單
<a href="javascript:window.prompt('輸入內容將替換當前頁面!','');undefined;">A</a> //將undefined加到最後
儘管javascript偽協議提供了一定的靈活性,但在頁面中儘量不要使用!而對於除錯JavaScript,javascript偽協議則顯得十分有用!