深入理解javascript選擇器API系列第一篇——4種元素選擇器
前面的話
說到最常見的DOM應用,恐怕就要數取得特定的某個或某組元素的引用了。DOM定義了許多方式來選取元素,包括getElementById()、getElementsByTagName()、getElementsByName()和document.all4種。接下來,將對這4種方法進行詳細介紹
getElementById()
任何HTML元素可以有一個id屬性,在文件中該值必須唯一
[注意]若瀏覽器中出現多個id名的情況,CSS樣式對所有該id名的元素都生效,但javascript指令碼僅對第一個出現該id名的元素生效
getElementById()該方法接收一個引數:要取得元素的id,若找到則返回該元素,若不存在則返回null
<div id="myDiv"></div> <script> var div1 = document.getElementById('myDiv'); var div2 = document.getElementById('mydiv'); console.log(div1);//<div id="myDiv"></div> console.log(div2);//null </script>
關於getElementById()方法,IE7-瀏覽器有兩個bug
【1】該方法對匹配元素的ID不區分大小寫
<div id="myDiv" style="height:20px;"></div> <script> var div1 = document.getElementById('mydiv'); //在標準瀏覽器下報錯,但在IE7-瀏覽器下,id為'myDiv'的元素的背景顏色變為品紅色 div1.style.backgroundColor = 'pink'; </script>
【2】表單元素的name屬性也會被當作ID屬性識別出來。因此為了避免這種問題,最好不讓表單元素的name屬性和其他元素的ID屬性相同
<button name="test">0</button> <script> varmyDiv = document.getElementById('test'); //在標準瀏覽器下報錯,但在IE7-瀏覽器中會輸出0 console.log(myDiv.innerHTML); </script>
[注意]如果在HTML文件中元素中存在某id屬性,並且如果Window物件沒有此名字的屬性, Window物件會賦予一個屬性,它的名字是id屬性的值,而它們的值指向表示文件元素的HTMLElement物件,因此,元素ID隱式地成為了全域性變數,與getElementById(id)方法的效果相同
<div id="test"></div> <button id="btn">按鈕一</button> <button id="location">按鈕二</button> <script> var oBtn = document.getElementById('btn'); var oDiv = document.getElementById('test'); oBtn.onclick = function(){ //通過getElementById()方法獲取id為test的物件 oDiv.style.height='10px'; //通過id屬性獲取相同的物件 test.style.backgroundColor ='pink'; } //由於location本身就是window物件下的屬性,已經被佔用,所以無法表示id=location的元素 location.onclick = function(){ alert(2); } </script>
在IE瀏覽器中,HTML某些元素如果有name屬性,也與id屬性相同,隱式地成為全域性變數,包括:
<a> <embed> <form> <iframe> <img> <object>
id是唯一的,但name屬性並不是唯一的。具有該名稱的隱式全域性變數會引用一個類陣列物件,包括所有該命名的元素
<a href="#" name="test">a元素1</a> <a href="#" name="test">a元素2</a> <div id="test">div元素</div> <script> //IE瀏覽器中,兩個a元素和一個div元素字型都變成紅色 for(var i = 0; i < test.length; i++){ test[i].style.color = 'red'; } </script>
【丟失的this】
document.getElementById這個方法名實在有點過長,可以用一個短的函式來代替它
var getId = function(id){ return document.getElementById(id); }
但是,為什麼不能用下面這種更簡單的形式呢?
var getId = document.getElementById; getId('div1');
上面的這段程式碼中會丟擲異常
這是因為document.getElementById方法的內部實現需要用到this,這個this本來被期望指向document,當getElementById方法作為document物件的屬性被呼叫時,方法內部的this確實指向document。但當用getId來引用document.getElementById之後,再呼叫getId,此時就成了普通函式呼叫,函式內部的this指向了window,而不是document
程式碼修改如下,可以取得id為'div1'的元素
<div id="div1"></div> <script> var getId = document.getElementById; console.log(getId.call(document,'div1')); </script>
或者,可以這樣修改
var getId = document.getElementById.bind(document);
最終結果如下
getElementsByTagName()
getElementsByTagName()方法接收一個引數,即要取得元素的標籤名,而返回的是包含0或多個元素的類陣列物件HTMLCollection。可以使用方括號語法或item()方法來訪問類陣列物件中的項,length屬性表示物件中元素的數量
<div>元素一</div> <div>元素二</div> <script> var divs = document.getElementsByTagName('div'); divs[0].style.color = 'red'; divs.item(1).style.backgroundColor = 'pink'; </script>
[注意]通過getElementsByTagName()方法取得的類陣列物件有一個namedItem()方法,可以通過元素的name屬性取得集合中的第一個值。safari和IE不支援該方法
<div>元素一</div> <div name='test'>元素二</div> <div name='test'>元素三</div> <script> var divs = document.getElementsByTagName('div'); divs.namedItem('test').style.color = 'red'; </script>
getElementsByTagName()方法可以用於document物件,也可以用於element元素物件,用於呼叫該方法的元素的後代元素
<ul id='myUl'> <li>1</li> <li>2</li> </ul> <script> var oUl = document.getElementById('myUl'); var lis = oUl.getElementsByTagName('li'); lis[0].style.color = 'red'; </script>
getElementsByName()
getElementsByName()方法會返回帶有給定name特性的所有元素
<button name='test'>按鈕一</button> <button name='test'>按鈕二</button> <script> var button = document.getElementsByName('test'); button[0].style.color = 'red'; </script>
關於getElementsByName()方法,IE瀏覽器與其他瀏覽器相比,有三個不同之處
【1】IE9-瀏覽器只支援在表單元素上使用getElementsByName()方法
<div name='test'>元素一</div> <div name='test'>元素二</div> <script> //標準瀏覽器下,元素一顏色變為紅色,但在IE9-瀏覽器下會報錯 var divs = document.getElementsByName('test'); divs[0].style.color = 'red'; </script>
【2】IE9-瀏覽器中使用getElementsByName()方法也會返回id屬性匹配的元素。因此,不要將name和id屬性設定為相同的值
<button name='test'>按鈕一</button> <button name='test'>按鈕二</button> <button id="test">按鈕三</button> <script> //標準瀏覽器下,按鈕三不變色,但IE9-瀏覽器下,按鍵三也變成紅色 var buttons = document.getElementsByName('test'); for(var i = 0; i < buttons.length; i++){ buttons[i].style.color = 'red'; } </script>
【3】如果對getElementsByName()方法取得的類陣列物件使用namedItem()方法,因為每一項的name屬性都相同,所以只會返回第一項
[注意]只有IE8——IE11瀏覽器支援
<button name='test'>按鈕一</button> <button name='test'>按鈕二</button> <script> var buttons = document.getElementsByName('test'); buttons.namedItem('test').style.color = 'red'; </script>
document.all
在DOM標準化之前,IE4就引入了document.all[]集合來表示文件中的所有元素
<div>div</div> <button>按鈕</button> <script> console.log(document.all);//[html, head, meta, title, body, div, button, script] //標準瀏覽器返回8,而IE8-瀏覽器返回9,由於它把文件宣告<!DOCTYPE html>識別為註釋,且把註釋識別為元素,所以多1個 console.log(document.all.length); </script>
現在document.all方法已經棄用,要取得類似效果,可以使用document.getElementsByTagName('*')方法,*表示匹配所有元素
<div>div</div> <button>按鈕</button> <script> console.log(document.getElementsByTagName('*'));//[html, head, meta, title, body, div, button, script] //標準瀏覽器返回8,而IE8-瀏覽器返回9,由於它把文件宣告<!DOCTYPE html>識別為註釋,且把註釋識別為元素,所以多1個 console.log(document.getElementsByTagName('*').length); </script>
最後
getElementsByName()方法並不常用,再加上已經廢棄的document.all。實際上,常用的獲取元素的方法就getElementById()和getElementsByTagName()兩種。getElementsByClassName()不也是嗎?確實是,但它和querySelector()等方法都是HTML5擴充的新方法,相容性不是很好,這些新方法將在續篇進行詳細介紹
歡迎交流