将链接的方法附加到JavaScript中的元素集合
问题描述:
这是 - 至少在此刻 - 纯粹是实验,但我很好奇:有没有一种方法可以将方法(通过原型设计)附加到元素集合?我测试了以下代码:将链接的方法附加到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中工作?该浏览器的相当于NodeList
是HTMLCollection
,但尝试原型后者根本不成功。建议?
答
我已经做好了我认为可以作为一个可行的解决方案;使用这种方法链接修改一组元素有什么根本性的坏处吗?
<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"]);
答
下面是你需要什么,而不是设置它的原型,因为一个“漂亮”的版本(没有的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";
});
是的,你不需要EVAL这一点。 也因为你实际上只有2个参数,为什么不命名他们和使用参数[]数组? – BYK 2009-04-19 10:52:27