JavaScript NodeList

有没有办法join由2个document.getElementsByTagName调用返回的2个NodeLists?

说,我有以下代码

var inputs = documentElement.getElementsByTagName('input'); var selects = document.getElementsByTagName('select'); 

我想循环的结果。 在一个循环中可能吗?

先谢谢你!

看起来像你可以使用相同的Array.prototype.slice.call,使参数数组类似的对象成为一个数组。 ( 见这里 )

 var inputs = document.getElementsByTagName('input'); var selects = document.getElementsByTagName('select'); inputs = Array.prototype.slice.call(inputs); selects = Array.prototype.slice.call(selects); var res = inputs.concat(selects); alert(res.length); 

你不能join它们,但是你仍然可以像这样在一个循环中依次循环它们:

 for ( var i = 0; i < inputs.length + selects.length; i++ ) { var element = ( i < inputs.length ) ? inputs[i] : selects[i-inputs.length]; } 

另外,使用jQuery,你可以一次select它们:

 $('input, select') 
 document.querySelectorAll("input, select"); 

据我所知, NodeListtypes是不可变的(例如见这篇文章 ),这意味着你将不得不生成自己的对象。

一个简单的方法就是创build一个数组并将所有元素复制到该数组中。

 var inputs = documentElement.getElementsByTagName('input'); var selects = document.getElementsByTagName('select'); var all = new Array(inputs.length + selects.length); var index = 0; for (i = 0; i < inputs.length; i++) all[index++] = inputs[i]; for (i = 0; i < selects.length; i++) all[index++] = selects[i]; 

然后allvariables包含两组节点的联合。

 function mergeNodeLists(a, b) { var slice = Array.prototype.slice; return slice.call(a).concat(slice.call(b)); } 

console.log( mergeNodeLists( inputs, selects ) ); // => [input, select]

我把它扔在一起。 对每个循环做一个if.length可能会有一些开销,但是除非元素的数量变得极端,否则我认为它很小。

 inputs = div.getElementsByTagName('input'); selects = div.getElementsByTagName('select'); for (i=0; i<inputs.length+selects.length; i++) { element = (i<inputs.length ? inputs[i] : selects[i-inputs.length]); // do whatever with element } 

我的书签小代码:

 var e, t = d.getElementsByTagName('textarea'), u = d.getElementsByTagName('input'), i = t.length; while(e = (i > 0) ? t[--i] : u[-i--]){ if(e.offsetHeight > 0)... } 

首先,我认为可以使用Array.prototype来连接数组,如下所示:

 Array.prototype.concat.call(selects, inputs); 

但它不起作用,所以我从节点集合中创build了一个数组并将其连接起来。 看起来像这样:

 (function () { var inputs = document.getElementsByTagName('input'), selects = document.getElementsByTagName('select'), result, i, node; function convert (collection) { var a = []; for (var i = 0, length = collection.length; i < length; i++) { a.push(collection[i]); } return a; } // concatenation && convertation result = Array.prototype.concat(convert(inputs), convert(selects)); // traversing i = result.length; while(node = result[--i]) { alert(node.getAttribute('name')); } })(); 

现在我肯定会使用以下内容:

Chrome,Firefox 3.5+,IE8 +

 var elements = document.querySelectorAll('a'); for (var i = 0, element; (element = elements[i]); i++) { console.log(element); } 

IE11 +,Firefox 24+,Chrome 30+(已启用实验)

 let elements = document.querySelectorAll('a'); for (let i = 0, element; (element = elements[i]); i++) { console.log(element); } 

“element = elements [i]”优于“elements.length”,因为:

“节点列表通常被实现为具有filter的节点迭代器,这意味着获得像长度一样的属性是O(n),并且通过重新检查长度来遍历列表将是O(n ^ 2)。

不像数组访问,这是我记得O(1)。

更多细节:

Array.prototype.slice.call()在IE 7中失败,使用这个:

 Object.prototype.getMyElements = function(tags){ tags = tags.split(','); var i, j, col=[], ci=0; for(i=0; i<tags.length; i++) { var objs = this.getElementsByTagName(tags[i]); for(j=0; j<objs.length; j++) col[ci++] = objs[j]; } return col; } var objs = document.getMyElements('INPUT,TEXTAREA'); var objs = document.getElementById('myform').getMyElements('INPUT,TEXTAREA'); 

试试我的方式:

  var allES = []; var inputs = document.getElementsByTagName("input"); for (i = 0; i < inputs.length; i++) { allES.push(inputs[i]); } // gather SELECT elements var selects = document.getElementsByTagName("select"); for ( i=0; i < selects.length; i++){ allES.push(selects[i]); } 

你为什么不尝试jQuery。

jQuery Traverse API参考