Concat可以与普通数字和字符串数组一起使用,但无法与对象数组一起使用。
实际上,它可以,但是NodeList
实例没有concat
方法,Array#concat
没有一种识别您想要展开它们的方式(因为它们不是数组)。
但这仍然相当容易做到(尽管请注意下面的警告)。更改此行:
var allTags = allInputs.concat(allSelects)
to
var allTags = [];
allTags.push.apply(allTags, allInputs);
allTags.push.apply(allTags, allSelects);
演示 | 源代码
这个技巧的原理是: Array#push
接受变量数量的元素添加到数组中,Function#apply
调用函数时使用给定的值作为 this
(在我们的例子中是 allTags
)以及任何类似数组的对象作为要传递给它的参数。由于 NodeList
实例是类似数组的对象,因此 push
很高兴地将列表的所有元素推入数组中。
Function#apply
的这种行为(不需要第二个参数真正是一个数组)在规范中被非常清楚地定义,并且在现代浏览器中得到了很好的支持。
遗憾的是,IE6和7不支持上述特性(我认为它特别是在使用宿主对象 NodeLists
作为 Function#apply
的第二个参数时),但是,我们也不应该支持 它们。:-) IE8也不支持,这更有问题。IE9是可以的。
如果您需要支持 IE8 及更早版本,那么遗憾的是,我认为你只能使用一个老套的循环:
var allInputs = document.getElementsByTagName('input');
var allSelects = document.getElementsByTagName('select');
var allTags = [];
appendAll(allTags, allInputs);
appendAll(allTags, allSelects);
function appendAll(dest, src) {
var n;
for (n = 0; n < src.length; ++n) {
dest.push(src[n]);
}
return dest;
}
实时示例 | 源代码
这个确实可以在IE8及更早版本(以及其他浏览器)上运行。