簡體   English   中英

在 ES6 中過濾或映射節點列表

[英]Filter or map nodelists in ES6

在 ES6 中過濾或映射節點列表的最有效方法是什么?

根據我的讀數,我將使用以下選項之一:

[...nodelist].filter

或者

Array.from(nodelist).filter

你會推薦哪一個? 還有沒有更好的方法,例如不涉及數組?

  • [...nodelist]將創建一個對象的數組,如果該對象是可迭代的。
  • 如果對象是可迭代的或者對象是類似數組的(具有.length和數字屬性Array.from(nodelist)Array.from(nodelist)將從對象中創建一個數組

如果NodeList.prototype[Symbol.iterator]存在,您的兩個示例將是相同的,因為這兩種情況都涵蓋可迭代對象。 但是,如果您的環境尚未配置為使NodeList可迭代,則您的第一個示例將失敗,而第二個示例將成功。 Babel目前沒有正確處理這種情況

因此,如果您的NodeList是可迭代的,則完全取決於您使用哪個。 我可能會根據具體情況進行選擇。 Array.from一個好處是它需要映射函數的第二個參數,而第一個[...iterable].map(item => item)必須創建一個臨時數組Array.from(iterable, item => item)不會。 但是,如果您沒有映射列表,則沒有關系。

TL; 博士;

Array.prototype.slice.call(nodelist).filter

slice() 方法返回一個數組。 返回的數組是集合 (NodeList) 的淺拷貝 所以它比 Array.from()工作得更快 所以它和Array.from()一樣快

原始集合的元素被復制到返回的數組中,如下所示:

  • 對於對象引用(而不是實際對象),切片將對象引用復制到新數組中。 原始數組和新數組都指向同一個對象。 如果引用的對象發生更改,則更改對新數組和原始數組都可見。
  • 對於字符串、數字和布爾值(不是字符串、數字和布爾對象),切片將值復制到新數組中。 對一個數組中的字符串、數字或布爾值的更改不會影響另一個數組。

關於論點的簡短解釋

Array.prototype.slice(beginIndex, endIndex)

  • 采用可選參數 beginIndex 和 endIndex。 如果沒有提供切片,則使用 beginIndex == 0,因此它從集合中提取所有項目

Array.prototype.slice.call(命名空間,beginIndex,endIndex)

  • 將一個對象作為第一個參數。 如果我們使用一個集合作為一個對象,它的字面意思是我們直接從該對象的namespace.slice()調用 slice 方法

我找到了一個直接在 NodeList 上使用map參考

Array.prototype.map.call(nodelist, fn)

我還沒有測試過它,但是這看起來可能會更快,因為它應該直接訪問 NodeList。

這個怎么樣:

// Be evil. Extend the prototype.
if (window.NodeList && !NodeList.prototype.filter) {
  NodeList.prototype.filter = Array.prototype.filter;
}

// Use it like you'd expect:
const noClasses = document
  .querySelectorAll('div')
  .filter(div => div.classList.length === 0)

它與NodeList.forEach 的 MDN 文檔(在“Polyfill”下)中提到的方法相同,它適用於 IE11 、Edge、Chrome 和 FF。

在 ES6 中過濾或映射節點列表

我從這個簡單的功能中走出來。 @see https://developer.mozilla.org/fr/docs/Web/API/NodeList/entries#exemple

function filterNodeList(NodeList, callback) {
if (!typeof callback === "function") callback = (i) => i; // Any have better idear?

const Result = document.createElement("div");
//# No need to filter empty NodeList
if (Node.length === 0) return Node;

for (let i = 0; i < Node.length; i++) {
  if (callback(Node.item(i))) Result.appendChild(Node.item(i));
}

return Result.childNodes;}

我願意了解更多:>

[...a].filterArray.from(a).filter

不是“真正的”性能差異, Array.from可能會快一點,因為您沒有在“JS 級別”上創建新的Array ,但它直接發生在本機代碼中。

性能 - 考慮使用任何一個

但是,為了提高性能(並避免“ Array -ing”),您應該考慮為什么要過濾NodeList以及您從哪里/如何獲得它。 在許多情況下,您只需要按id或按class或其他 CSS 選擇器的特定元素。

document.querySelectorAll快 10 倍 - 200 倍,適用於任何 CSS 選擇器
document.getElementById甚至更快(但當然需要一個id

你甚至可以優化querySelectorAll或繞過“未知”的情況,如果你提供一個預先存儲的父項來查看,讓我舉個例子:

let mainbar = document.getElementById('mainbar');
mainbar.querySelectorAll('.flex--item');

幾乎快 10 倍於

Array.from(a).filter(el => el.classList.contains("flex--item"))

還要注意document.querySelectorAll('#mainbar .flex--item'); 仍然比Array過濾快約 5 倍,但比使用id預存儲父節點慢約 2 倍。

除了更好的性能之外,您還將始終獲得NodeList (它可能是空的,但仍然是NodeList ),這適用於document.querySelectorAll()Element.querySelectorAll()

使用 ECMAS 2016:

let nodes = [...document.querySelector('__SELECTOR__').childNodes].filter(item => item.nodeType === 1);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM