1. 程式人生 > >深入理解javascript選擇器API系列第一篇——4種元素選擇器

深入理解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>
var
myDiv = 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擴充的新方法,相容性不是很好,這些新方法將在續篇進行詳細介紹

  歡迎交流