2009-03-02 90 views
1

這是 - 至少在此刻 - 純粹是實驗,但我很好奇:有沒有一種方法可以將方法(通過原型設計)附加到元素集合?我測試了以下代碼:將鏈接的方法附加到JavaScript中的元素集合

<div>a</div> 
<div>b</div> 
<div>c</div> 
<script> 
NodeList.prototype._ = function(s) 
{ 
    for (x = 0; x < this.length; x++) 
    { 
     eval('this[x]' + '.' + s); 
    } 
    return this; 
} 
document.getElementsByTagName('div')._("style.backgroundColor = 'red'")._('innerHTML += x'); 
</script> 

此刻,它在Opera中完美運行;就像所期望的那樣,_方法在所有div元素上被調用,然後eval()依次將傳遞給它的字符串轉換爲。請注意,_方法允許鏈接,並且已被證明,調用_將迭代器變量的預測附加到每個元素的innerHTML。

現在,兩個問題...

首先,有沒有要去這個更好的辦法?我有最長的希望,我只能做document.getElementsByTagName('div').style.backgroundColor = "red";,但唉,它根本還沒有成爲現實。這就是我首先這樣做的原因,爲什麼我這麼簡潔地命名該方法;我試圖儘可能地模仿它。

其次,假設這是一個理智的用法,我將如何着手讓它在Firefox中工作?該瀏覽器的相當於NodeListHTMLCollection,但嘗試原型後者根本不成功。建議?

回答

1

我已經做好了我認爲可以作爲一個可行的解決方案;使用這種方法鏈接修改一組元素有什麼根本性的壞處嗎?

<script> 
_ = function() 
{ 
    for (x = 0; x < arguments[0].length; x++) 
    { 
     for (y = 0; y < arguments[1].length; y++) 
     { 
      eval('arguments[0][x]' + '.' + arguments[1][y]); 
     } 
    } 
} 
</script> 

用法:

divs = document.getElementsByTagName('div'); 
_(divs, ["style.color = 'red'", "innerHTML += x"]); 
+0

是的,你不需要EVAL這一點。 也因爲你實際上只有2個參數,爲什麼不命名他們和使用參數[]數組? – BYK 2009-04-19 10:52:27

0

下面是你需要什麼,而不是設置它的原型,因爲一個「漂亮」的版本(沒有的eval,沒有全局,正式參數,字符串內沒有的fugly代碼)這對IE不起作用。

/** 
* Sets a property on each of the elements in the list 
* @param {NodeList} list 
* @param {string} prop The name of property to be set, 
*  e.g., 'style.backgroundColor', 'value'. 
* @param {mixed} value what to set the value to 
*/ 
function setListProp(list, prop, value) {  
    for (var i = 0; i < list.length; i++) { 
     setProp(list[i], prop, value); 
    } 
} 

/** 
* Avoids the use of eval to set properties that may contain dots 
* Why avoid eval? eval is slow and could be dangerous if input comes from 
* an unsanitized source 
* @param {object} el object that will have its property set 
* @param {string} propName ('value', 'style.backgroundColor') 
* Example: setProp(node, 'style.backgroundColor', "#ddd"); 
*/ 
function setProp(el, propName, value) { 
    var propList = propName.split('.'); 
    // Note we're not setting it to the last value in the property chain 
    for (var i=0; i < propList.length - 1 ; i++) { 
     el = el[propList[i]]; 
    } 
    var lastProperty = propList[propList.length -1]; 
    el[lastProperty] = value; 
} 

測試用例 訪問google.com使用Firefox,輸入上面的代碼到控制檯,然後輸入以下命令:

// Set tooltip on links 
setListProp(document.getElementsByTagName('a'), 'title', 'YEAH it worked'); 


// Set bg to red on all links 
setListProp(document.getElementsByTagName('a'), 'style.backgroundColor', '#f00'); 

UPDATE 我的解決方案贏得了」如果你希望能夠像你剛纔提到的那樣做,我認爲最優雅的解決方案是使用如下的回調循環。

/** 
* This exists in many libs and in newer versions of JS on Array's prototype 
* @param {Object[]} arr The array that we want to act on each element. 
*     Does not work for sparse arrays 
* @param {Function} callback The function to be called for each element, it will be passed 
*  the element as its first argument, the index as the secibd 
*/ 
function iterate(arr, callback) { 
    for (var i=0,item; item=arr[i]; i++) { 
    callback(item, i); 
    } 
} 

然後,你可以這樣調用

var as = document.getElementsByTagName('a'); 
iterate(as, function(el, index) { 
    el.style.backgroundColor = 'red'; 
    el.innerHTML += "Whatever"; 
}); 
相關問題