成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

前端開發必備:Maps與WeakMaps在DOM節點管理中的妙用

開發 前端
使用 Maps 和 WeakMaps 可以提高代碼的可讀性和可維護性。將DOM節點與相關數據關聯起來,有助于使代碼更清晰易懂。

這篇文章討論了使用 Maps 和 WeakMaps 處理DOM節點的優勢。Maps 和 WeakMaps 是非常實用的工具,尤其在處理大量DOM節點時,它們發揮著重要作用。

文章作者認為,使用 Maps 和 WeakMaps 處理 DOM 節點有以下幾個優點。首先,它們可以方便地存儲和檢索數據。與其他數據結構相比,Maps和 WeakMaps 可以更簡潔地組織和查找相關數據。其次,它們可以幫助開發者更好地管理內存。當不再需要某個DOM節點時,WeakMaps可以自動釋放與該節點相關的內存,從而提高程序的性能。最后,使用 Maps 和 WeakMaps 可以提高代碼的可讀性和可維護性。將DOM節點與相關數據關聯起來,有助于使代碼更清晰易懂。

下面是正文:

在JavaScript中, 我們經常使用普通的對象來存儲鍵/值數據,它們非常擅長這項工作 - 清晰易讀:

const person = {
 firstName: 'Alex', 
 lastName: 'MacArthur', 
 isACommunist: false
};

但是,當我們開始處理經常被讀取、更改和添加屬性的較大實體時,更傾向于使用 Maps。因為在某些情況下,Map 比對象具有多個優勢,特別是性能問題或插入順序比較重要的情況下。

但最近我特別喜歡使用它們來處理大量的DOM節點。

在閱讀Caleb Porzio最近的博客文章時,我想到了這個想法。在這篇文章中,他正在使用由10,000個表行組成的表格,其中一個可以是“active”。為了管理選擇不同行時的狀態,使用對象作為鍵/值存儲。這是他的一個迭代版本的注釋版本。

import { ref, watchEffect } from 'vue';

let rowStates = {};
let activeRow;

document.querySelectorAll('tr').forEach((row) => {
    // Set row state.
    rowStates[row.id] = ref(false);

    row.addEventListener('click', () => {
        // Update row state.
        if (activeRow) rowStates[activeRow].value = false;

        activeRow = row.id;

        rowStates[row.id].value = true;
    });

    watchEffect(() => {
        // Read row state.
        if (rowStates[row.id].value) {
            row.classList.add('active');
        } else {
            row.classList.remove('active');
        }
    });
});

它使用一個對象作為大型哈希映射表,因此用于關聯值的鍵必須是字符串,因此需要在每個項目上存在唯一的ID(或其他字符串值)。這帶來了一些額外的編程開銷,需要在需要時生成和讀取這些值。

任何對象都可以作為鍵

相反,使用 Map 可以讓我們直接將 HTML 節點作為鍵。因此,該代碼片段最終看起來像這樣:

import { ref, watchEffect } from 'vue';

- let rowStates = {};
+ let rowStates = new Map();
let activeRow;

document.querySelectorAll('tr').forEach((row) => {
- rowStates[row.id] = ref(false);
+   rowStates.set(row, ref(false));

    row.addEventListener('click', () => {
-       if (activeRow) rowStates[activeRow].value = false;
+       if (activeRow) rowStates.get(activeRow).value = false;

        activeRow = row;

-       rowStates[row.id].value = true;
+       rowStates.get(activeRow).value = true;
    });

    watchEffect(() => {
-       if (rowStates[row.id].value) {
+       if (rowStates.get(row).value) {
            row.classList.add('active');
        } else {
            row.classList.remove('active');
        }
    });
});

這里最明顯的好處是我不需要擔心每行存在唯一ID。節點引用本身是唯一的,可以作為鍵。因此,既不需要設置也不需要讀取任何屬性。這更簡單、更具彈性。

讀/寫操作通常更高效

當我們處理更大的數據集時,操作的性能顯著提高。甚至在規范中也有說明 - 必須以保持性能的方式構建 Map,以便隨著項目數量的增加而增長:

Maps must be implemented using either hash tables or other mechanisms that, on average, provide access times that are sublinear on the number of elements in the collection.

“Sublinear” 的意思是性能不會隨著 Map 的大小成比例地下降。因此,即使是大型 Map,性能也應該保持相當迅速。

再次強調,沒有必要干擾DOM屬性或通過類似字符串的ID執行查找。每個鍵本身就是一個引用,這意味著我們可以跳過一兩個步驟。

我進行了一些基本的性能測試來確認所有這些。首先,按照Caleb的場景,我在頁面上生成了10,000個 <tr> 元素:

const table = document.createElement('table');
document.body.append(table);

const count = 10_000;
for (let i = 0; i < count; i++) {
  const item = document.createElement('tr');
  item.id = i;
  item.textContent = 'item';
  table.append(item);
}

接下來,我設置了一個模板來測量循環遍歷所有這些行并將一些相關狀態存儲在對象或Map中需要多長時間。我還在 for 循環中運行了同樣的過程多次,然后確定編寫和讀取所需的平均時間。

const rows = document.querySelectorAll('tr');
const times = [];
const testMap = new Map();
const testObj = {};

for (let i = 0; i < 1000; i++) {
  const start = performance.now();

  rows.forEach((row, index) => {
    // Test Case #1  
 // testObj[row.id] = index;
 // const result = testObj[row.id];

 // Test Case #2
 // testMap.set(row, index);
 // const result = testMap.get(row);
  });

  times.push(performance.now() - start);
}

const average = times.reduce((acc, i) => acc + i, 0) / times.length;

console.log(average);

我用不同的行大小運行了這個測試:

圖片

請記住,即使是稍微不同的情況,這些結果也可能會有很大的差異,但總體而言,它們通常符合我的預期。在處理相對較少的項目時,Map 和對象之間的性能是可比的。但隨著項目數量的增加,Map 開始拉開差距。性能的次線性變化開始顯現。

WeakMaps更有效地管理內存

有一個特殊版本的 Map 接口,旨在更好地管理內存 - WeakMap 。它通過保持對其鍵的“弱”引用來實現這一點,因此,如果這些對象鍵中的任何一個不再具有其他地方綁定的引用,則它有資格進行垃圾回收。因此,當不再需要該鍵時,整個條目將自動從 WeakMap 中刪除,從而清除更多內存。它也適用于DOM節點。

為了調整這個,我們將使用 FinalizationRegistry ,它會在你正在觀察的引用被垃圾回收時觸發回調。我們將從幾個列表項開始:

<ul>
  <li id="item1">first</li>
  <li id="item2">second</li>
  <li id="item3">third</li>
</ul>

接下來,我們將把這些項目放入 WeakMap 中,并將 item2 注冊為注冊表監視的對象。我們將其刪除,每當它被垃圾回收時,回調將被觸發,我們將能夠看到 WeakMap 如何發生變化。

但是...垃圾收集是不可預測的,也沒有官方的方法來觸發它,因此為了測試,我們將定期生成一堆對象并將它們保存在內存中。以下是整個腳本:

(async () => {
 const listMap = new WeakMap();

 // Stick each item in a WeakMap.
 document.querySelectorAll('li').forEach((node) => {
  listMap.set(node, node.id);
 });

 const registry = new FinalizationRegistry((heldValue) => {
  // Garbage collection has happened!
  console.log('After collection:', heldValue);
 });

 registry.register(document.getElementById('item2'), listMap);
    
 console.log('Before collection:', listMap);

 // Remove node, freeing up reference!
 document.getElementById('item2').remove();

  // Periodically create a bunch o' objects to trigger collection.
  const objs = [];
  while (true) {
     for (let i = 0; i < 100; i++) {
   objs.push(...new Array(100));
  }

  await new Promise((resolve) => setTimeout(resolve, 10));
 }
})();

在發生任何事情之前,WeakMap 如預期的那樣包含三個項。但是在從DOM中刪除第二項并進行垃圾收集之后,它看起來有點不同

圖片

由于節點引用在DOM中不再存在,整個條目已從 WeakMap 中刪除,從而釋放了更多的內存。這是一個很 nice 功能,有助于使環境的內存更加整潔。

責任編輯:姜華 來源: 大遷世界
相關推薦

2024-11-07 09:08:58

2010-09-08 15:13:09

Node節點Node屬性

2010-09-08 15:16:46

clearCSS

2010-09-09 16:54:05

CSSclear

2024-04-25 08:22:43

AndroidlargeHeap屬性

2022-07-13 09:01:17

前端開發文件處理庫

2023-02-24 14:52:20

Redis存儲開發

2022-02-17 20:34:12

Python短路機制開發

2019-03-12 10:38:18

前端開發Nginx

2022-01-21 19:00:44

前端JS框架

2020-11-26 08:38:57

前端 js 庫vue

2019-11-19 16:45:09

Web前端開發編碼原則

2023-12-29 09:04:01

前端文件處理庫PDF.js

2010-08-30 16:02:06

CSSclear

2021-02-16 08:16:09

適配器模式MybatisJava

2021-04-08 10:40:24

前端工具代碼

2024-02-04 09:18:00

Python內存管理垃圾回收

2021-04-01 07:52:57

前端開發技術熱點

2010-03-10 17:57:54

Python編程語言

2010-09-09 17:19:07

HTML DOMXML DOM
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲夜射 | 一区二区三区四区在线 | 天天操夜夜操免费视频 | 国产高清精品一区二区三区 | 久久伊人亚洲 | 久久国产精品一区二区三区 | 在线观看av中文字幕 | 亚洲精品黑人 | 亚洲精品片 | 免费在线观看91 | 男女在线网站 | 欧日韩在线 | 久久精品99| 精品亚洲永久免费精品 | 日韩中文一区二区三区 | 91www在线观看 | 欧美一级片在线观看 | 午夜av一区二区 | 国产一区精品 | 中文一级片 | 韩国av网站在线观看 | 日本在线中文 | 欧美三区在线观看 | av网站免费观看 | 瑟瑟激情 | 国产精品一区三区 | 日本三级线观看 视频 | 欧美精品一区二区三区在线 | 欧美激情久久久 | 亚洲综合在线一区二区 | 婷婷在线网站 | 99国产精品久久久久久久 | 范冰冰一级做a爰片久久毛片 | 国产高清免费视频 | 韩日一区二区三区 | 97人人草| av一级 | 久久综合九九 | 亚洲国产成人久久综合一区,久久久国产99 | 亚州国产| 欧美日韩免费在线 |