2012-11-08 78 views
2

大量的JavaScript庫(jQuery的,的Zepto)似乎對querySelectorAll()被調用Array.prototype.slice.call,getElementsByTag或類名結果...爲什麼Array.prototype.slice.call(nodeList)爲DOM元素?

從StackOverflow上讀很多很多類似的問題/答案我做了解它將NodeList結果轉換爲真實數組,以便您可以對NodeLists上不可用的結果調用Array方法(slice,pop) - 但是我不明白爲什麼?您通常不需要在DOM節點列表上真正需要slice/pop + NodeLists已經具有length屬性,因此無論如何它們都可以遍歷。

一些答案似乎暗示它是因爲NodeList指向活動的DOM對象。但是,如果將它轉換爲數組,那麼引用仍然指向活動的DOM節點 - 那又有什麼區別?

或者是我完全失蹤的其他東西?它有助於Zepto/jQuery以某種方式緩存DOM元素的多個屬性調用? (雖然我實在不明白如何,因爲那些仍然生活DOM引用)

+1

你說得對,一個'NodeList'指向活DOM對象,但這意味着當一個被銷燬(或不再是列表的有效項)時,它和它的位置將從列表中刪除。當你切入一個數組時,它不是同一個「實時」列表 - 元素本身是活的,但不是列表本身。當一個物品被銷燬時,它的位置仍然保留在數組中......但它不會代表該元素 - 我猜測它變成了未定義或爲空。 – Ian

+0

@Ian如果一個數組包含對DOM節點的引用,那麼該節點_cannot_將被垃圾收集。 – Alnitak

+0

@Alnitak我明白了,那麼我猜我的評論會改成像「」,它的位置仍然保留在數組中,元素保持不變,直到沒有更多的引用爲止......然後,數組將是未定義的或爲空「。這是正確的嗎? – Ian

回答

2

你通常不會真的需要DOM的名單上切片/ PoP節點

其實,你這樣做,這正是爲什麼它是必要的。

例如,.eq(),.first()等將如何工作。 jQuery對象在數組中包含一個副本NodeList,然後各個方法對該數組進行切片。同樣,您不能將.add()節點設置爲NodeList

此外,即使其中的元素隨後從DOM中移除,這些數組也需要保持有效。數組中的引用仍然有效,可用於將這些元素重新插入到DOM中。

如果你只是一個活的NodeList元素將從列表中自動消失,當它們從DOM中刪除,並將永遠丟失,除非你有一個單獨的引用。

+0

@TinyGiant _some_'NodeList'對象是活的,有些是靜態的。 'querySelectorAll'返回的是靜態的。建議您閱讀上述問題的實質性評論。 – Alnitak

+0

請注意,如果nodeList是SVG元素,Array.prototype.slice.call(nodeList)在某些IE版本上不起作用 –

0

...因爲一個節點列表指向住DOM對象...

沒有,這是一種誤解。關鍵並不是列表中的每個節點都是「實時」DOM對象(真實但無關緊要),這就是列表本身是「實時」的。換句話說,每當DOM被改變時,列表的內容可能隨時改變(甚至增長或縮小)。

如果您對列表中用於更改DOM的項目執行操作,那麼當您使用列表時,列表本身可能會隨時更改。這意味着在你的代碼中,你的代碼可能會陷入非常奇怪的遞歸和/或性能問題,而你沒有意識到它,並且在源代碼中幾乎沒有任何指示。

將NodeList轉換爲常規的Javascript Array可以消除列表本身的「活性」,從而消除了在腳中拍攝自己的機會。

+0

@TinyGiant某些肯定是,例如, 'aNode.childNodes'。你的例子使用'querySelectorAll',它返回一個非活的NodeList。 – 1983

相關問題