简体   繁体   English

JavaScript NodeList

[英]JavaScript NodeList

is there a way to join 2 NodeLists returned by 2 calls of document.getElementsByTagName? 有没有办法加入2个调用document.getElementsByTagName返回的2个NodeLists?

Say, I have the following code 说,我有以下代码

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

I want to loop through the results. 我想循环结果。 Is it possible in one loop? 有可能在一个循环中吗?

Thank you in advance! 先感谢您!

Seems like you can use the same Array.prototype.slice.call that makes the args array-like object become an array. 好像你可以使用相同的Array.prototype.slice.call,它使args数组类对象成为一个数组。 ( See here ) 见这里

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);

You can't join them, but you can still loop through them sequentially in one loop like this: 你不能加入它们,但你仍然可以在一个循环中顺序循环它们,如下所示:

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

Alternatively, using jQuery, you could select them all in one go: 或者,使用jQuery,您可以一次性选择它们:

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

As far as I know, the NodeList type is immutable (see this article for example), which means you'll have to generate your own object. 据我所知, NodeList类型是不可变的(例如参见本文 ),这意味着你必须生成自己的对象。

A simple method would just be to create an array and copy all the elements into that array. 一个简单的方法就是创建一个数组并将所有元素复制到该数组中。

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];

The all variable then contains the union of the two sets of nodes. 然后, all变量包含两组节点的并集。

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

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

My short code for bookmarklets: bookmarklet的简短代码:

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)... }

I threw this together. 我把它扔在了一起。 There might be a bit of overhead from doing an if and .length for every loop, but I think its minor unless the number of elements get extreme. 为每个循环执行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
}

Nowadays I would definitely use the following: 现在我肯定会使用以下内容:

Chrome, Firefox 3.5+, IE8+ 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+ (with experiments enabled) 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]" is preferred over "elements.length" since: “element = elements [i]”比“elements.length”更受欢迎,因为:

"Node lists are often implemented as node iterators with a filter. This means that getting a property like length is O(n), and iterating over the list by re-checking the length will be O(n^2)." “节点列表通常被实现为带有过滤器的节点迭代器。这意味着获取像length这样的属性是O(n),并且通过重新检查长度迭代列表将是O(n ^ 2)。”

Unlike array access, which is as far as I remember O(1). 与数组访问不同,这是我记得的O(1)。

More details: 更多细节:

Array.prototype.slice.call() fails in IE 7, use this: 在IE 7中,Array.prototype.slice.call()失败,请使用:

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');

try my way: 试试我的方式:

 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]);
                }

First, I thought that this is possible to concat arrays using Array.prototype, like this: 首先,我认为这可以使用Array.prototype来连接数组,如下所示:

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

But it doesn't work, so that I've made an arrays from node collections and concat it. 但它不起作用,所以我从节点集合中创建了一个数组并将其连接起来。 Looks like that: 看起来像这样:

(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'));
    }

})();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM