在JavaScript中合并两个对象(节点列表)数组

在JavaScript中合并两个对象(节点列表)数组,javascript,arrays,object,merge,Javascript,Arrays,Object,Merge,我正在尝试将两个对象数组合并到,以便验证表单。通常的concat方法在这种情况下似乎不起作用。Concat适用于普通的数值数组和字符串数组,但不适用于对象数组。行var allTags=allInputs.concat(allSelects)不起作用 var allInputs = document.getElementsByTagName("input"); alert("Inputs: " + allInputs.length); var allSelects = document.get

我正在尝试将两个对象数组合并到,以便验证表单。通常的concat方法在这种情况下似乎不起作用。Concat适用于普通的数值数组和字符串数组,但不适用于对象数组。行
var allTags=allInputs.concat(allSelects)不起作用

var allInputs = document.getElementsByTagName("input");
alert("Inputs: " + allInputs.length);

var allSelects = document.getElementsByTagName("select");
alert("Selects: " + allSelects.length);

var allTags = allInputs.concat(allSelects);
alert("allTags: " + allTags.length);
Concat适用于普通的数值数组和字符串数组,但不适用于对象数组

实际上,它是这样的,但是
NodeList
实例没有
concat
方法,而且
Array#concat
没有一种方法来确定您想要展平这些实例(因为它们不是数组)

但这仍然相当容易做到(不过请参见下面的警告)。更改此行:

var allTags = allInputs.concat(allSelects);

|

这是通过使用一些技巧实现的:接受可变数量的元素添加到数组中,并使用
this
(在我们的例子中,
allTags
)的给定值和任何类似数组的对象作为传递给它的参数来调用函数。由于
NodeList
实例类似于数组,
push
愉快地将列表中的所有元素推送到数组中

Function#apply
(不要求第二个参数真正是数组)的这种行为在规范中定义得非常清楚,在现代浏览器中得到了很好的支持

遗憾的是,IE6和IE7不支持上述内容(我认为它专门使用主机对象--
节点列表--
-for
函数#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;
}
var allInputs=document.getElementsByTagName('input');
var allSelects=document.getElementsByTagName('select');
var-allTags=[];
appendAll(所有标签、所有输入);
appendAll(所有标签,所有选择);
函数appendAll(dest,src){
var n;
对于(n=0;n
|


这对IE8和早期版本(以及其他版本)有效。

是否研究过underline.js?你可以

 var allSelectsAndInputs = _.union(_.values(document.getElementsByTagName("input")),_.values(document.getElementsByTagName("select")));
有关更多信息,请参阅:


该函数用于对象,但在此设置下工作。

document.get[something]
返回a,它看起来非常类似于,但具有许多不同的功能,其中两个是:

  • 它不包含concat方法
  • 项目列表是实时的。这意味着它们会随着文档的实时更改而更改
如果在将节点列表转换为实际阵列方面没有任何问题,可以执行以下操作以实现所需的效果:

var allInputs  = document.getElementsByTagName("input")
  , allSelects = document.getElementsByTagName("select")
;//nodeLists

var inputList  = makeArray(allInputs)
  , selectList = makeArray(allSelects)
;//nodeArrays

var combined   = inputList.concat(selectList);

function makeArray(list){
  return Array.prototype.slice.call(list);
}

您将失去原始节点列表的任何和所有行为,包括它实时更新以反映DOM更改的能力,但我的猜测是,这不是一个真正的问题。

您正在处理的是
HTMLCollection
s,它们是实时集合(即,当您将节点添加到DOM中时,它将自动添加到集合中

不幸的是,它没有一个
concat
方法…这是有原因的。您需要做的是将它转换为一个数组,失去它的活动行为:

var allInputsArray = [].slice.call(allInputs),
    allSelectsArray = [].slice.call(allSelects),
    allFields = allInputsArray.concat(allSelectsArray);

我找到了一种简单的方法,可以按照dom对象在页面或表单上的显示顺序收集它们。 首先,在对象上创建一个伪类样式“reqd”,然后使用下面的命令,按照它们在页面上出现的顺序创建一个列表。只需将该类添加到您希望收集的任何对象中即可

var allTags = document.querySelectorAll("input.reqd, select.reqd");

这不是数组,而是类似于数组的对象(NodeList)事实上,它是一个NODLIST,因此不具有CONTAT方法。实际上,我正在玩它。它看起来有点关闭。站起来。如果你喜欢它,考虑投票我的答案。@ USER 2035797:不用担心,我现在还添加了一个在IE8和更早的作品上的例子。预先警告,就像我在ANSW的第一部分中给出的类似的解决方案一样。呃,这在IE8或更早版本中是行不通的。(在这里试试:)唉,至少IE9是不错的。所以对于IE8或更早版本,你需要一个无聊的老循环。
var allTags = document.querySelectorAll("input.reqd, select.reqd");