如何避免使用 ES9 的 Array.prototype.includes() 出现的错误

ES9(ECMAScript 2018)引入了一个方便的方法 Array.includes(),它可以检测一个数组是否包含某个元素。然而,在进行元素比较时,它会使用 JavaScript 的内置 SameValueZero 算法,这可能会导致错误。

在本文中,我们将介绍这个问题的背景和原因,并提供几种避免这个问题的方法。

问题的背景

Array.includes() 方法将使用 SameValueZero 算法去比较数组元素和待查找元素。简单说,如果两个值完全相同,则返回 true。但是,这种比较可能不是我们想要的。

考虑如下示例,我们将两个对象添加到数组中,它们具有相同的内容但是却是不同的实例:

----- --- - -- --- - -- - --- - ---
----- --- - - --- - --
------------------------------- -- -----

这个结果可能出乎意料。尽管数组中包含 id 属性值为 1 的对象,但是 Array.includes() 返回了 false。这是因为 obj 对象和数组中的对象在 JavaScript 中是不同的实例。

这个问题可能在以下情况下产生:

  • 在使用流行的 Redux 状态管理库时,通常需要在 Redux 中比较对象。如果你使用了 Array.includes(),可能会遇到这个问题。
  • 当你比较两个由不同组件传递到 React 组件时的对象时,也可能会遇到这个问题。

解决方案

现在我们已经了解了问题所在,那么如何避免这个问题呢?以下是一些解决方案。

1. 使用 Array.find() 方法代替 Array.includes()

Array.find() 方法可以接受一个回调函数作为参数。这个函数将应用于数组中的每个元素,直到它找到一个值满足回调函数的条件。如果找到这样的值,则返回该值,否则返回 undefined。这通常是一种更可靠的比较方法。

以下是一个将 Array.find() 用于上面示例的方法:

----- --- - -- --- - -- - --- - ---
----- --- - - --- - --
----- --- - ------------- -- ----- --- --------
------------------- -- ----

2. 扩展 Array.prototype

你可以扩展 Array 对象的原型,并提供一个自定义的 includesDeep() 方法。这个方法将会使用深度优先的对象比较算法,以检查数组中是否存在一个给定的元素。

以下是一个实现这个方法的简单示例:

---------------------------- - -------- -------- -
  ------ ---------------- -- -
    ------ ------------- --------
  --
-

-------- -------------- ------ -
  ----- ---- - --------------------------------------
  -- ----- --- -------------------------------------- ------ ------
  -- ---------- -------- -------- ----------------------- - -- ------ ----- --- ------
  ----- -------- - ---- --- -------- ------- - ------------ - --------------------------
  ----- -------- - ---- --- -------- ------- - ------------ - --------------------------
  -- --------- --- --------- ------ ------
  ----- ------- - -------- ------- ------ -
    ----- -------- - --------------------------------------
    -- ---------- -------- -------- --------------------------- -- -- -
      -- ---------------- ------- ------ ------
    -
    ---- -
      -- --------- --- -------------------------------------- ------ ------
      -- --------- --- -------- ----------- -
        -- ----------------- --- ----------------- ------ ------
      -
      ---- -
        -- ------ --- ------ ------ ------
      -
    -
  --
  -- ----- --- -------- -------- -
    --- ---- - - -- - - --------- ----
      -- ------------------- ---------- ------ ------
  -
  ---- -
    --- ------ --- -- ------ -
      -- --------------------------- -
        -- --------------------- ------------ ------ ------
      -
    -
  -
  ------ -----
-

由于这个方式可能会造成命名冲突,所以我们建议只在需要使用自定义 includesDeep() 方法的文件中添加这个方法。

使用 includesDeep() 方法将确保在比较数组元素和查找元素时使用深度比较算法。例如:

----- --- - -- --- - -- - --- - ---
----- --- - - --- - --
----------------------------------- -- ----

3. 使用 Lodash 库

Lodash 是一个流行的 JavaScript 实用程序库,包含数百个工具方法。其中一个工具是 _.isEqual(),它可以用于深度比较两个值。

以下是用 Lodash 中的 _.isEqual() 来改写上面的示例的一个例子:

----- --- - -- --- - -- - --- - ---
----- --- - - --- - --
----------------------- ---- -- ------------- ------- -- ----

_.some() 方法和 ECMAScript 2018 一样,都接受一个回调函数作为参数。当任何一个元素传递给回调函数并返回一个真值时,_.some() 跳出循环,并返回 true。使用 _.isEqual() 比较两个对象,以确保它们具有相同的内容。

结论

在使用 JavaScript 中的 Array.includes() 方法时,需要小心使用。这可能会导致错误的结果,导致应用程序的不稳定。

我们提供了三种不同的解决方案来避免这个问题。在使用任何这些方法时,都需要考虑到性能和可读性方面的因素,确保代码优雅、健壮和可扩展。

来源:JavaScript中文网 ,转载请联系管理员! 本文地址:https://www.javascriptcn.com/post/66f6c545c5c563ced58bddb6


猜你喜欢

  • 使用Vue.js与Web Components结合开发的经验分享

    前言 在现代Web开发中,开发者面临着不断增加的技术栈和复杂度。Vue.js和Web Components是其中非常流行的前端开发技术,它们提供了强大的组件化架构和完善的生命周期管理,在构建可扩展的W...

    2 个月前
  • 如何在 CSS Reset 的基础上进行样式调整?

    引言 在进行网页开发时,不同浏览器对 CSS 样式的渲染方式可能存在差异。为了避免这些差异带来的样式不统一问题,我们通常会在样式表中添加一些常用的 CSS Reset 样式。

    2 个月前
  • ESLint + Prettier 配置,让代码风格更整洁

    前言 作为前端开发人员,我们经常需要写出可读性高、规范、结构化的代码。这样有利于让其他人更快地了解代码含义,是一个好的开发习惯,能够提高项目的可维护性。ESLint 和 Prettier 是两个非常优...

    2 个月前
  • Docker 容器中文乱码的原因与解决方法

    前言 Docker 是一个非常流行的容器化技术,用它可以打包、分发和运行应用程序。但是在使用 Docker 容器过程中,有时会出现中文乱码的情况,这不仅仅影响美观,更会影响容器内部的应用程序正常运行。

    2 个月前
  • ES6 中的模板标签和模板字符串

    随着前端技术的不断发展,ES6 成为了不可忽视的一部分。其中,模板标签和模板字符串是 ES6 中非常重要的特性之一。 在本文中,我们将深入介绍模板标签和模板字符串,并提供实用的例子和管理方法,以便更好...

    2 个月前
  • 无障碍设计:如何为辅助功能用户提供更好的服务?

    随着人们对辅助功能的需求不断增长,无障碍设计已成为现代网站设计中必不可少的一环。本文将介绍无障碍设计的重要性、常见的几种辅助功能技术以及设计中的最佳实践。 什么是无障碍设计? 无障碍设计指的是为所有用...

    2 个月前
  • jest-environment-jsdom-sixteen 和 Enzyme: 如何解决 React 新版本的兼容问题

    在开发 React 应用时,经常会遇到各种兼容性问题。在新版本 React 发布时,它的生命周期方法和 API 可能会发生变化。这就导致了我们的测试用例不再适用于新版本的 React。

    2 个月前
  • 在 Deno 中实现可靠的日志系统的方法

    在现代 Web 应用程序中,日志是一项必不可少的功能之一。记录日志有助于开发人员跟踪应用程序的行为,查找错误,并监控应用程序的性能。在 Deno 中,实现一个可靠的日志系统是非常简单的,本文将介绍如何...

    2 个月前
  • 创建可观察的主题和 RxJS 升级教程

    在前端领域中,有时我们需要实现一些实时更新的功能,比如实时搜索、自动完成等等。这时候我们会使用一种叫做“可观察对象”的编程模式来实现这些功能。 本文将详细介绍如何创建可观察的主题,并通过 RxJS 的...

    2 个月前
  • 解决 Next.js 在页面切换时白屏的问题

    背景 Next.js 是一种流行的 React 框架,它提供了很多单页应用程序 (SPA) 没有的服务器端渲染 (SSR) 功能。但是,在实际开发中,我们经常会遇到一个问题:页面切换时会出现白屏。

    2 个月前
  • 如何在 React 项目中引入 Redux

    Redux 是一个状态管理库,它可以用于在 React 应用程序中管理应用程序的状态。Redux 将应用程序状态存储在一个单一的“状态树”中,并允许通过 dispatching actions 来更改...

    2 个月前
  • 使用 Node.js 和 Express.js 创建 REST API 的最佳实践

    REST(Representational State Transfer)是一个常用的用于创建 Web 服务的架构样式。现在,许多 Web 应用程序都使用 REST API 以实现各种功能,如建立用户...

    2 个月前
  • 使用 ES6 的 Promise.allSettled 解决异步请求状态问题

    在前端开发中,我们常常需要进行异步请求,而这些请求往往需要一定时间才能完成,而此时我们需要对请求的状态进行处理,以便向用户展示更为准确的信息。在 ES6 中,Promise.allSettled 这一...

    2 个月前
  • 使用 Jest 测试 React 组件时如何 mock 掉子组件的 props?

    当我们测试一个包含子组件的 React 组件时,有时我们可能需要 mock 掉子组件的一些属性或方法,以使测试更轻松、更可预测。本文将介绍如何在使用 Jest 进行 React 组件测试时 mock ...

    2 个月前
  • 如何在 Enzyme + React 中解决 setState 异步更新的问题

    在 React 应用中,当组件的状态需要更新时,我们通常会使用 setState 方法。然而,由于 setState 方法是异步更新的,这可能会导致在测试时出现一些问题。

    2 个月前
  • Redis 如何应对因半同步复制带来的读写性能问题

    介绍 Redis 是一个开源的高性能键值对数据库系统,应用广泛于互联网和移动互联网等领域。在 Redis 中,半同步复制是常用的复制策略之一。然而,在使用半同步复制时,由于主从节点之间的网络延迟,可能...

    2 个月前
  • 使用 Mocha 测试框架减少 JavaScript 错误率的技巧

    在进行 JavaScript 开发的过程中,避免错误是非常重要的。错误会导致代码崩溃、数据丢失以及安全漏洞等问题。使用测试框架可以帮助我们快速准确地发现问题。本文将介绍如何使用 Mocha 测试框架减...

    2 个月前
  • Node.js 中的人工智能技术详解

    人工智能已经成为了当今前端开发领域不可或缺的一部分。Node.js 作为最流行的前端开发工具之一,其拥有强大的基础设施和广泛的社区支持,为前端开发者提供了许多先进的人工智能技术。

    2 个月前
  • Performance Optimization: 使用 APK Analyzer 优化 Android 应用大小和性能

    作为一个前端开发者,我们不仅需要关注应用的外观和交互体验,还需要关注应用的性能和文件大小。在 Android 应用开发中,我们可以使用 APK Analyzer 工具来优化我们的应用。

    2 个月前
  • CSS Flexbox:利用伸缩和流布局实现自适应布局

    在前端开发中,设计自适应布局是一项重要的技能。CSS Flexbox 是一个强大的布局工具,它允许我们在不同屏幕大小和设备上创建适应性很强的布局。本文将深入介绍 CSS Flexbox 的实现原理和使...

    2 个月前

相关推荐

    暂无文章