我的getElementsByClassName實現

來源:互聯網
上載者:User

先來看一下代碼:(支援多個class查詢和在某個範圍內進行查詢)

/* * 根據元素clsssName得到元素集合 * @param fatherId 父元素的ID,預設為document * @tagName 子項目的標籤名 * @className 用空格分開的className字串 */function getElementsByClassName(fatherId,tagName,className){var node = fatherId&&document.getElementById(fatherId) || document;tagName = tagName || "*";className = className.split(" ");var classNameLength = className.length;for(var i=0,j=classNameLength;i<j;i++){//建立匹配類名的正則className[i]= new RegExp("(^|\\s)" + className[i].replace(/\-/g, "\\-") + "(\\s|$)"); }var elements = node.getElementsByTagName(tagName);var result = [];for(var i=0,j=elements.length,k=0;i<j;i++){//緩衝length屬性var element = elements[i];while(className[k++].test(element.className)){//最佳化迴圈if(k === classNameLength){result[result.length] = element;break;}}k = 0;}return result;}

好,我們來測試一下:

<div id="container">  <span class="aaa zzz ccc"></span>  <div class="aaa bbb ccc"></div></div><div class="aaa bbb ccc"></div>
window.onload = function(){alert(getElementsByClassName(document,"div","aaa ccc").length);//2alert(getElementsByClassName("container","div","aaa ccc").length);//1alert(getElementsByClassName("container","span","aaa zzz").length);//1}

正確的得到了結果。

 

關於class屬性

1.一個元素可以帶有多個class屬性值,它們通過空格分隔, 例:class='aa bb cc'。

2.class屬性值是可以包含'-'這個字元的,如:class='a-b',特彆強調是因為在Regex中'-'是一個特殊字元。

3.在javascript中通過的擷取class屬性值的方式為element.className。

 

原生的getElementsByClassName

有人會問,原生的方法調用效率是最高的,有很多瀏覽器已經將實現了getElementsByClassName這個方法,那為什這裡沒有先調用原生的再調用自訂的呢?

對,原生的效率是很高,它支援多個class條件的查詢,但是最大的問題是他不支援getElementsByClassName("container","div","aaa ccc"),這種在指定標籤中尋找指定元素為指定class的情況。

所以,這裡捨棄了原生的方法調用。

 

關於迴圈最佳化的問題

在代碼中,你會看到我將數組的length緩衝了起來,這樣可以提高效率。其實上,在這裡有一個很隱形問題,就是數組訪問length屬性和HtmlCollection訪問length有很在的區別。在數組中,length是一個普通的屬性,訪問時不會進行額外的操作,在來看看HTMLCollection,我們常常將HTMLCollection當作數組來使用,但實際上,它是一個根據DOM結構自動變化的實體物件。每次訪問一個HTMLCollection對象的屬性時,他都會對DOM內所有的節點進行一次完整的匹配。也就是說,每次訪問HtmlCollection對象的length時,都會更新一次集合對象,效能上消耗很大。所以一般情況之下,這種HtmlCollection的迴圈操作,都是建議緩衝length的。

 

 

額外的收穫

 這是關於往數組裡放元素的方式間,效率比較的問題

來看一下代碼:

//方式一var arr = [];var start = new Date();for(var i=0;i<100000;i++){arr.push(i);}//方式二var arr = [];var start = new Date();for(var i=0;i<100000;i++){arr[arr.length]=i;}

猜猜看,哪種效率更高呢!經過測試,第二種方式的效率要高於第一種。

 

提醒:

這個版本是不相容IE5的,以下是我給出的解釋:

1.當你從那千分之幾的統計資料裡,再去瘋錢的IE5測試人員的點擊和專業程式員對IE5的好奇心,估計就只剩IE5被焚燒後的灰燼了。

2.你要想信灰燼的利用價值趨於零

3.如果到現在還沒能說服你,那我想說,你很專業!即然這樣,那還有IE3,IE2,IE?FF1,NN4...,我想你應該一併實現了。

 

一些坦白:我也不怎麼說服得了我自已,唉,還是給一個IE5的解決方案吧:

 IE5並不支援getElementByTagName("*")的形式,所以在這裡要處理一下:

var elements = (tagName==='*'&&node.all)?node.all:node.getElementsByTagName(tagName);

好了,不多說的,這個函數簡單實用,代碼上我也寫了注釋,看明白應該已經沒有什麼問題了

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.