在 JavaScript 中合并两个对象 (NodeList) 数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14665295/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 17:32:29  来源:igfitidea点击:

Merging two object (NodeList) arrays in JavaScript

javascriptarraysobjectmerge

提问by user2035797

I am attempting to merge two arrays of objects to so I can validate a form. The usual concat method does not appear to work in this circumstance. Concat works with ordinary numerical and string arrays but doesn't with object arrays. The line var allTags = allInputs.concat(allSelects);does not work.

我正在尝试合并两个对象数组,以便我可以验证表单。在这种情况下,通常的 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);

回答by T.J. Crowder

Concat works with ordinary numerical and string arrays but doesn't with object arrays.

Concat 适用于普通的数字和字符串数组,但不适用于对象数组。

Actually, it does, but NodeListinstances don't have a concatmethod, and Array#concatdoesn't have a means of identifying that you want to flatten those (because they're not arrays).

实际上,它确实如此,但是NodeList实例没有concat方法,并且Array#concat没有识别您想要展平它们的方法(因为它们不是数组)。

But it's still fairly easy to do (see caveat below, though). Change this line:

但这仍然很容易做到(不过,请参阅下面的警告)。改变这一行:

var allTags = allInputs.concat(allSelects);

to

var allTags = [];
allTags.push.apply(allTags, allInputs);
allTags.push.apply(allTags, allSelects);

Live Example| Source

现场示例| 来源

That works by using a bit of a trick: Array#pushaccepts a variable number of elements to add to the array, and Function#applycalls the function using the given value for this(in our case, allTags) and any array-like object as the arguments to pass to it. Since NodeListinstances are array-like, pushhappily pushes all of the elements of the list onto the array.

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

This behavior of Function#apply(not requiring the second argument to really be an array) is veryclearly defined in the specification, and is well-supported in modern browsers.

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

Sadly, IE6 and 7 don't support the above (I think it's specifically using host objects — NodeLists — for Function#apply's second argument), but then, we shouldn't be supporting them, either. :-) IE8 doesn't, either, which is more problematic. IE9 is happy with it.

可悲的是,IE6 和 7 不支持上述(我认为它专门使用主机对象NodeLists ——作为Function#apply第二个参数),但是,我们也不应该支持它们。:-) IE8 也没有,这更成问题。IE9 对此很满意。

If you need to support IE8 and earlier, sadly, I think you're stuck with a boring old loop:

如果您需要支持 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;
}

Live Example| Source

现场示例| 来源

That doeswork on IE8 and earlier (and others).

确实适用于 IE8 及更早版本(和其他版本)。

回答by THEtheChad

document.get[something]returns a NodeList, which looks very similar to an Array, but has numerous distinctive features, two of which are:

document.get[something]返回一个NodeList,它看起来与Array非常相似,但具有许多独特的功能,其中两个是:

  • It does not contain the concat method
  • The list of items is live. This means they change as the document changes in real time.
  • 它不包含 concat 方法
  • 项目列表是实时的。这意味着它们会随着文档的实时变化而变化。

If you don't have any issues with turning your NodeLists into actual arrays, you could do the following to achieve the effect you desire:

如果您在将 NodeLists 转换为实际数组时没有任何问题,您可以执行以下操作来达到您想要的效果:

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

You will lose any and all behaviors of the original NodeList, including it's ability to update in real time to reflect changes to the DOM, but my guess is, that's not really an issue.

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

回答by MaxArt

What you're dealing with are HTMLCollections, and they're livecollections (i.e., when you add a node to the DOM, it's automatically added to the collection.

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

And sadly, it doesn't have a concatmethod... for a reason. What you need to do is to convert it to an array, losing its live behaviour:

可悲的是,它没有concat方法……是有原因的。您需要做的是将其转换为数组,从而失去其实时行为:

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

回答by FutureMode

I found a simple way to collect dom objects in the order they appear on a page or form. Firstly, create a dummy class style 'reqd' on the object then use the following which creates a list in the order they appear on the page. Just add the class to any objects you wish to collect.

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

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

回答by Zeke Alexandre Nierenberg

Looked into underscore.js at all? You could do

研究过 underscore.js 吗?你可以做

 var allSelectsAndInputs = _.union(_.values(document.getElementsByTagName("input")),_.values(document.getElementsByTagName("select")));

For more information see: http://underscorejs.org/#extend

有关更多信息,请参阅:http: //underscorejs.org/#extend

The function is intended for objects, but works in this setting.

该功能适用​​于对象,但在此设置中有效。