2009-09-10 74 views
0

不使用任何開源框架(jQuery等):),在JavaScript中,在任何控件中搜索屬性的最有效方法是什麼。 (任何舊的/新的瀏覽器)JavaScript中的搜索屬性

這是我跟隨的模式。有沒有更好的方法或更好的方法?謝謝!

e.g

<input type="button" id="b1" value="Continue" a1="something" /> 
<input type="text" id="t1" a1="something1" /> 

<script> 
var attrToFind = "something;something1"; 

var elems = document.all ? document.all : document.getElementByTagName("*"); 
//assume elems work always 
for(var i = 0 ; i < elems.length; i++) 
{ 
    var att = elems[i].getAttribute("a1"); 
    if (typeof att == "string") 
    { 
    if (att.indexOf(attrToFind) > -1) 
    ... //search which attr you find, create array, save value, etc. 
    } 
} 
</script> 
+1

我認爲你已經有了非常正確的想法......你的測試很弱 - 如果價值是「somethingelse」,它會匹配「某事」 - 但這很容易修復。更大的問題在於,對於大型文檔來說它會很慢,因爲它每次都必須遍歷整個DOM。這就是爲什麼諸如jQuery/Sizzle之類的選擇器引擎會鼓勵更具體的選擇器:'input [a1 = something]'只需要測試輸入元素。 – Shog9 2009-09-10 22:34:02

回答

1

有。鑑於瀏覽器支持其他方式來收集元素,例如document.querySelectorAll(css表達式)或document.evaluate(xpath表達式),所以這些「專業」方法通常更高效。

document.querySelectorAll('*[foo="bar"]'); 
document.evaluate("//*[@foo='bar']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); 
+0

@kangax:有趣...根本不知道querySelectorAll。我相信它不適用於新舊瀏覽器,所以我無法真正使用它。 @ Shog9:是的,我的方式越來越慢,這也是我的擔心。這就是爲什麼我在這裏發佈問題來問問JS大師。 – 2009-09-11 00:01:25

+0

是的,你最終不得不編寫一個使用這些方法之一的包裝函數(如果可用),否則就會退回到整個文檔中。這是許多框架所做的事情(儘管其中一些沒有得到字符串轉義的權利......) – bobince 2009-09-11 01:19:47

1

訪問一個HTMLCollection(由getElement[s]By*函數返回)是相比於訪問陣列因爲HTMLCollection必須在任何時候(它是活)匹配文檔緩慢

由於這個原因,最好從HTMLCollection創建一個數組,然後迭代它。

這是速度有點更優化:

var attrToFind = "something;something1", 
    elems = document.all ? document.all : document.getElementByTagName('*'), 
    i, attr; 

// Works in Firefox; not sure about other browsers and engines. 
elems = Array.prototype.slice.call(elems); 

i = elems.length; 

while(i --> 0) { 
    attr = elems[i].getAttribute('a1'); 

    // Are you sure you want indexOf? 
    // att === attrToFind may be faster, as it requires one less comparison. 
    if(typeof att !== 'string' || att.indexOf(attrToFind) < 0) { 
     continue; 
    } 

    // Do stuff. 
} 
+0

@stranger:代碼片段看起來很樂觀。讓我嘗試。謝謝! – 2009-09-11 01:11:00

+0

是的,IE6不喜歡Array.prototype.slice.call(elems),不幸的是(我們所有人)都支持它。 – 2009-09-11 01:32:03

+0

@ Rac123,您可能只需迭代並將其複製到IE6的新陣列即可。或許,在當前的集合到數組的行周圍添加一個try塊,而不是在天真的解決方案中捕獲。 – strager 2009-09-11 02:06:20

0

這也許是解決方案,您將需要:

function $$$$(obj) { 

var attrToFind = obj; 
var elements = document.getElementsByTagName('*'); 
var attrResults = []; 

var x = 0; 
while (x < elements.length) { 
    var attr = elements[x].getAttribute('a1'); 

    if (attr !== null) { 
     if (attr.indexOf(attrToFind) > -1) { 
      attrResults.push(elements[x]); 
     } 
    } 
    x++ 
} 
return attrResults; 

}

運行功能:

$$$$('something'); 

結果是一個數組所有與「類」類相關的元素。 也許有人可以重構我的代碼,所以這也適用於超過1個參數。

我希望我能幫助你。