2013-02-02 85 views
9

我正試圖合併兩個對象數組,以便我可以驗證表單。在這種情況下,通常的連接方法似乎不起作用。 Concat使用普通的數字和字符串數組,但不與對象數組一起使用。行var allTags = allInputs.concat(allSelects);不起作用。在JavaScript中合併兩個對象(NodeList)數組

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

這不是數組其陣列狀物體(節點列表) – salexch

+0

據,實際上的NodeList,並且因此不具有concat方法。 – THEtheChad

回答

19

的毗連的作品與普通的數字和字符串數組但不與對象數組。

事實上,確實如此,但NodeList情況下,沒有一個concat方法,並Array#concat沒有確定要扁平化的(因爲他們不是陣列)的一種手段。

但它仍然很容易做(請參閱下面的警告,雖然)。改變這一行:

var allTags = allInputs.concat(allSelects); 

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

Live Example | Source

即通過使用比特特技的工作原理: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; 
} 

Live Example | Source

確實在IE8及更早版本(及其他)上工作。

+0

非常感謝您的協助。我是一名初學者。 – user2035797

+0

@ user2035797:不用擔心,我現在還添加了一個適用於IE8及更早版本的示例。 –

+0

+1哇,感謝瀏覽器支持的所有信息! – Christophe

0

看着underscore.js呢?你可以做

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

欲瞭解更多信息,請參閱:http://underscorejs.org/#extend

的功能是爲對象,但在此設置工作。

+0

實際上,我在玩它......它似乎有點偏離。支持。 –

+2

不要建議使用這樣的圖書館一次性需要... – MaxArt

+0

我會檢查出下劃線謝謝 – user2035797

2

document.get[something]返回NodeList,這看起來非常類似於Array,但有許多鮮明的特點,其中兩個是:

  • 它不包含concat方法
  • 項目的列表是。這意味着它們會隨着文檔實時更改而發生變化。

如果你沒有與你轉成的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); 
} 

您將丟失所有和的所有行爲原始的NodeList,包括它能夠實時更新以反映DOM的變化,但我的猜測是,這不是一個真正的問題。

+0

需要預先警告的是,與我在答覆的第一部分給出的類似解決方案一樣,這不適用於IE8或更早的版本。 (嘗試在這裏:http://jsbin.com/iledok/1)*嘆*至少IE9是體面的。所以對於IE8和更早版本,需要一個無聊的舊循環。 –

1

你處理什麼是HTMLCollection s,而他們現場集合(即,當你添加一個節點到DOM,它會自動添加到集合。

可悲的是,這不是「T有concat方法......是有原因的,你需要做的是將其轉換爲一個數組,失去了生活的行爲。

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

我發現了一個簡單的方法來收集的順序DOM對象他們出現在一個頁面或表格上 首先,創建一個虛擬類樣式'reqd'在對象上,然後使用以下命令按照它們在頁面上顯示的順序創建一個列表。只需將該類添加到您希望收集的任何對象。

var allTags = document.querySelectorAll("input.reqd, select.reqd"); 
相關問題