」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 使用 Symbol.iterator 控制循環

使用 Symbol.iterator 控制循環

發佈於2024-11-18
瀏覽:179

Take control of loops with Symbol.iterator

您是否曾经使用过 Object.entries 并想知道它是如何工作的?比你想象的要简单得多!

这是一个基本实现:

function objectEntries(obj) {
  const entries = [];

  for (const key in obj) {
    if (Object.hasOwn(obj, key)) {
      entries.push([key, obj[key]]);
    }
  }

  return entries;
}

然而,这段代码还不够好——如果对象很大怎么办?在执行该函数的整个过程中,基于数组的方法的性能必须存储在内存中。如果你再次使用它呢?它必须同样构建并在内存中保存一个新数组。在现实世界中,这可能会导致严重的性能问题,并且在某些时候我们需要适应性能。然而,有一个优雅的解决方案可以解决所有这些问题,其中 Symbol.iterator 来拯救!

这是更新的片段:

function objectEntries(obj) {
  return {
    [Symbol.iterator]() {
      const keys = Object.keys(obj);
      let index = 0;

      return {
        next() {
          if (index 



为什么使用Symbol.iterator进行迭代?

在我们的初始实现中,objectEntries 函数在内存中构建所有条目([key, value] 对)的数组,如果对象具有大量属性,这可能会出现问题。将所有条目存储在数组中意味着我们必须提前为每一对分配内存。这种方法对于较小的对象来说相当不错,但随着对象大小的增加,它很快就会变得低效并且速度很慢。

在更新的代码中,我们在保存迭代逻辑的对象上定义[Symbol.iterator]。让我们一步步分解:

  • 初始化Keys:Object.keys(obj)从对象obj中获取键数组。这个键列表使我们能够准确地知道我们需要访问哪些属性,而无需存储每个条目。
  • 使用索引指针:变量索引跟踪我们在键数组中的当前位置。这是我们在循环中唯一的状态。
  • 定义 next 方法:next() 函数使用索引来检索当前键并递增它。它返回每个 [key, obj[key]] 对作为值,并在我们迭代所有键时设置 did: true。
  • 通过这样做,我们使 objectEntries 能够与任何 for...of 循环兼容,而无需预先创建整个条目数组的内存成本。

将 Symbol.iterator 应用于自定义循环

让我们更深入地了解这些方法如何提供对循环行为的更多控制。提供的每个示例都演示了与数组数据交互的独特方式,为您的代码增加了很大的灵活性。我们将探讨每种方法的含义以及如何在不同场景中利用它们。

在这些示例中,我将使用示例方法扩展数组原型(有关原型的更多信息),以使我的代码更易于阅读。让我们直接进入吧!

例如,此反向迭代器方法在聊天应用程序之类的应用程序中很有用,您可能希望首先显示最新的消息。聊天应用程序因拥有大量数据(在本例中为消息)而臭名昭著。使用reverseIterator,您可以迭代消息列表并按所需顺序显示它们,而无需创建新的反向数组。

Array.prototype.reverseIterator = function() {
  let index = this.length - 1;
  return {
    [Symbol.iterator]: () => ({
      next: () => {
        if (index >= 0) {
          return { value: this[index--], done: false };
        }
        return { done: true };
      }
    })
  };
};

const numbers = [1, 2, 3, 4, 5];
for (const num of numbers.reverseIterator()) {
  console.log(num); // 5, 4, 3, 2, 1
}

这种独特的方法使您能够迭代数组,同时确保仅生成唯一值。这对于动态消除重复项非常有用,无需提前过滤并使用更多内存。

Array.prototype.unique = function() {
  const seen = new Set();
  return {
    [Symbol.iterator]: () => ({
      next: () => {
        for (let i = 0; i 



下面的 chunk 方法在处理大型数据集时非常有用,您可以将它们分成较小的块来处理,以减少内存使用并提高性能。假设您正在从 CSV 文件之类的文件导入数据,您可以在更具可扩展性的段中读取和处理它。此外,在 Web 用户界面中,分块可用于分页,允许您在每页显示特定数量的项目或帮助您更好地管理无限加载器。

Array.prototype.chunk = function(size) {
  let index = 0;
  return {
    [Symbol.iterator]: () => ({
      next: () => {
        if (index 



结论

在本文中,我们探讨了 Symbol.iterator 如何自定义逻辑并提高循环效率。通过在 Array.prototype(或任何其他可迭代的效果)上实现自定义可迭代方法,我们可以有效地管理内存使用并控制循环的运行方式。

objectEntries 的初始示例演示了基于数组的方法在处理大型对象时如何导致性能问题。然而,通过使用 SYmbol.iterator,我们创建了一个有效的解决方案,允许我们迭代对象条目,而无需不必要的内存分配开销。

我们还研究了几个实际示例,说明扩展 Array.prototype 如何促进开发人员日常处理的各种现实场景。

有了这些强大的工具,您可以更好地解决 JavaScript 中复杂的数据处理场景,对应用程序的性能影响几乎为零。

版本聲明 本文轉載於:https://dev.to/vanyaxk/take-control-of-loops-with-symboliterator-4lon?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • Go 中的 os.File.Write() 是執行緒安全的嗎?
    Go 中的 os.File.Write() 是執行緒安全的嗎?
    os.File.Write()的線程安全注意事項os.File.Write()函數是文件的基本部分在Go 中進行處理,從而能夠將資料寫入檔案。然而,了解這個函數從多個執行緒並發呼叫是否安全是至關重要的。 Go 文件中沒有明確提及 os.File.Write() 的線程安全性。一般來說,只有在明確聲明...
    程式設計 發佈於2024-11-18
  • 如何在 PHP 中組合兩個關聯數組,同時保留唯一 ID 並處理重複名稱?
    如何在 PHP 中組合兩個關聯數組,同時保留唯一 ID 並處理重複名稱?
    在 PHP 中組合關聯數組在 PHP 中,將兩個關聯數組組合成一個數組是常見任務。考慮以下請求:問題描述:提供的代碼定義了兩個關聯數組,$array1 和 $array2。目標是建立一個新陣列 $array3,它合併兩個陣列中的所有鍵值對。 此外,提供的陣列具有唯一的 ID,而名稱可能重疊。要求是建...
    程式設計 發佈於2024-11-18
  • 大批
    大批
    方法是可以在物件上呼叫的 fns 數組是對象,因此它們在 JS 中也有方法。 slice(begin):將陣列的一部分提取到新數組中,而不改變原始數組。 let arr = ['a','b','c','d','e']; // Usecase: Extract till index ...
    程式設計 發佈於2024-11-18
  • 儘管程式碼有效,為什麼 POST 請求無法擷取 PHP 中的輸入?
    儘管程式碼有效,為什麼 POST 請求無法擷取 PHP 中的輸入?
    解決PHP 中的POST 請求故障在提供的程式碼片段中:action=''而不是:action="<?php echo $_SERVER['PHP_SELF'];?>";?>"檢查$_POST數組:表單提交後使用var_dump檢查$_POST 陣列的內容。...
    程式設計 發佈於2024-11-18
  • 如何用 JavaScript 就地取代 DOM 元素?
    如何用 JavaScript 就地取代 DOM 元素?
    用 JavaScript 就地取代 DOM 元素取代 DOM 中的元素可能是 Web 開發中的有用技術。例如,如果您想將錨點 () 元素替換為跨度 () 元素,則可以使用 JavaScript 來替換。 取代 DOM 最有效的方法元素到位是利用replaceChild()方法。實作方法如下:取得 D...
    程式設計 發佈於2024-11-18
  • 紫色虛線揭示了網站擴展的哪些內容?
    紫色虛線揭示了網站擴展的哪些內容?
    紫色虛線之謎:揭開可用的擴展空間在網絡開發的複雜領域中,出現了一個奇怪的現象:一條淡紫色虛線,似乎裝飾著某些元素的外圍。這條線有什麼神祕的用途? 答案在於擴展領域。紫色虛線表示元素可以擴展其範圍的可用空間。例如,當應用於文字元素時,它表示文字擴展的潛在邊界。 隨著字元的添加或刪除,此虛線區域的長度會...
    程式設計 發佈於2024-11-18
  • 為什麼我的 MySQLi 查詢只回傳一行,而我期望回傳多行?
    為什麼我的 MySQLi 查詢只回傳一行,而我期望回傳多行?
    確定MySQLi 查詢僅檢索一行的根本原因當遇到MySQLi 查詢儘管期望多行但僅返回一行的問題時,有必要檢查所涉及的代碼。在所提供的情況下,查詢旨在從 sb_buddies 和 sb_users 表中檢索資料。 代碼從兩個表中選擇列,並根據 buddy_requester_id 欄位將它們連接起來...
    程式設計 發佈於2024-11-18
  • 在 Perl 和 Go 中探索密碼強度和數字驗證
    在 Perl 和 Go 中探索密碼強度和數字驗證
    在本文中,我将解决 Perl Weekly Challenge #287 中的两个挑战:加强弱密码和验证数字。我将为这两项任务提供解决方案,展示 Perl 和 Go 中的实现。 目录 加强弱密码 验证数字 结论 加强弱密码 第一个任务是确定使密码更安全所需的最少更改次...
    程式設計 發佈於2024-11-18
  • 如何使用 GopherLight 像專業人士一樣在 Go 中編寫 API
    如何使用 GopherLight 像專業人士一樣在 Go 中編寫 API
    文档 GopherLight 嘿伙计们,首先我要感谢您选择使用我们的项目。尽管他很小,但我们却以极大的热情做到了!要开始使用它,您首先必须安装 go,我们假设您已经安装了它。然后安装框架的主要模块,分别是req和router go get github.com/BrunoCicca...
    程式設計 發佈於2024-11-18
  • Bootstrap 4 Beta 中的列偏移發生了什麼事?
    Bootstrap 4 Beta 中的列偏移發生了什麼事?
    Bootstrap 4 Beta:列偏移的刪除和恢復Bootstrap 4 在其Beta 1 版本中引入了重大更改柱子偏移了。然而,隨著 Beta 2 的後續發布,這些變化已經逆轉。 從 offset-md-* 到 ml-auto在 Bootstrap 4 Beta 1 中, offset-md-*...
    程式設計 發佈於2024-11-18
  • 如何使用不同單位的無單位 CSS 變數?
    如何使用不同單位的無單位 CSS 變數?
    如何靈活地使用無單位CSS 變數無單位CSS 變數提供了儲存數值的能力,這些數值可以在整個樣式表中方便使用。然而,可能會出現這樣的情況:您希望在不同的上下文中使用相同的變量,需要不同的單位,例如百分比或像素。 這種困境的一個例子是設定一個值為 10 的 CSS 變量,但是需要在一個實例中將其用作百分...
    程式設計 發佈於2024-11-18
  • 當 #await 區塊在 Svelte(Kit) 中解析時執行函數
    當 #await 區塊在 Svelte(Kit) 中解析時執行函數
    跳至内容: 关于 svelte 中的 #await 块 当 #await 块解析或拒绝时运行(触发)函数 修复浏览器中显示的未定义或任何返回的文本 1. 方法一(返回空字符串): 2. 方法二(用CSS隐藏UI中函数返回的文本。) PS:需要雇用 SvelteKit 开发人员吗?联系我 ...
    程式設計 發佈於2024-11-18
  • 一個 Java 檔案中可以有多個類別嗎?
    一個 Java 檔案中可以有多個類別嗎?
    Java 檔案中的多個類別在 Java 中,單一 .java 檔案中可以有多個類別。不過,公共頂級類別只能有一個,而且必須與原始檔案同名。 一個文件中有多個類別的目的是為了組織邏輯上相關的程式碼。這些類別通常包括公共頂級類別的支援功能,例​​如內部資料結構或實用方法。透過將它們捆綁在一起,您可以將相...
    程式設計 發佈於2024-11-18
  • 如何有效測試PDO資料庫連線並處理錯誤?
    如何有效測試PDO資料庫連線並處理錯誤?
    測試PDO資料庫連線開發資料庫安裝時,確保資料庫連線的有效性至關重要。當嘗試建立預設設定時,這一點變得尤為重要。 PDO(PHP 資料物件)提供了一種測試有效和無效連接的有效方法。 驗證連線若要使用PDO 連線至MySQL 資料庫,語法為:$dbh = new pdo('mysql:host=127...
    程式設計 發佈於2024-11-18
  • 當現有值相同時,MySQL 更新查詢是否會覆寫它們?
    當現有值相同時,MySQL 更新查詢是否會覆寫它們?
    MySQL更新查詢:覆寫現有值在MySQL中,更新表時,可能會遇到這樣的情況:為列指定的新值是與其目前值相同。在這種情況下,自然會出現一個問題:MySQL 會覆寫現有值還是完全忽略更新? UPDATE 語句的 MySQL 文件提供了答案:如果將列設定為它目前的值,MySQL 會注意到這一點並且不會更...
    程式設計 發佈於2024-11-18

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3