目录
不变性:坚持事实
使用不变对象
React 中的不变性
Immutable.js
进一步阅读
首页 web前端 css教程 了解JavaScript中的不变性

了解JavaScript中的不变性

Apr 11, 2025 am 11:47 AM

Understanding Immutability in JavaScript

JavaScript 中的不变性概念可能与变量重新赋值容易混淆。使用 letvar 声明的变量可以重新赋值,但 const 声明的变量则不行。

例如,将 "Kingsley" 赋值给名为 firstName 的变量:

let firstName = "Kingsley";
登录后复制

可以重新赋值:

firstName = "John";
登录后复制

这是因为使用了 let。如果使用 const

const lastName = "Silas";
登录后复制

尝试重新赋值会报错:

lastName = "Doe";
// TypeError: Assignment to constant variable.
登录后复制

但这并非不变性。

在 React 等框架中,一个重要概念是避免直接修改状态 (state) 和属性 (props)。 不变性并非 React 独有概念,而是 React 在处理状态和属性时所利用的一个重要原则。

那么,不变性究竟是什么意思呢?

不变性:坚持事实

不变数据无法改变其结构或其中的数据。 它将值赋给一个不能更改的变量,使该值成为一个事实,或某种意义上的真相来源——就像公主亲吻青蛙,希望它变成英俊的王子一样。不变性意味着青蛙将永远是青蛙。

而对象和数组允许变异,这意味着数据结构可以更改。如果我们告诉它,亲吻这些青蛙中的任何一个都可能导致变成王子的转变。

例如,一个用户对象:

let user = { name: "James Doe", location: "Lagos" };
登录后复制

创建一个新的 newUser 对象:

let newUser = user;
登录后复制

如果第一个用户更改位置,它将直接修改 user 对象,并影响 newUser

user.location = "Abia";
console.log(newUser.location); // "Abia"
登录后复制

这可能不是我们想要的结果。这种重新赋值可能会导致意外后果。

使用不变对象

我们需要确保对象不被变异。如果要使用某个方法,它必须返回一个新对象。本质上,我们需要一个纯函数

纯函数具有两个特性:

  1. 返回值取决于传入的参数。只要输入不变,返回值就不会改变。
  2. 它不会更改其作用域之外的事物。

使用 Object.assign(),我们可以创建一个不会修改传入对象的函数。它将创建一个新的对象,并将第二个和第三个参数复制到作为第一个参数传入的空对象中,然后返回新对象。

const updateLocation = (data, newLocation) => {
  return Object.assign({}, data, { location: newLocation });
};
登录后复制

updateLocation() 是一个纯函数。如果我们传入第一个用户对象,它将返回一个新的用户对象,其中 location 属性具有新值。

另一种方法是使用扩展运算符:

const updateLocation = (data, newLocation) => {
  return { ...data, location: newLocation };
};
登录后复制

那么,这与 React 有什么关系呢?

React 中的不变性

在典型的 React 应用中,状态是一个对象。(Redux 使用不变对象作为应用程序存储的基础。)React 的协调过程确定组件是否应该重新渲染,或者它是否需要一种跟踪更改的方法。

换句话说,如果 React 无法确定组件的状态已更改,那么它将不知道要更新虚拟 DOM。

强制执行不变性使得跟踪这些更改成为可能。这允许 React 比较对象的旧状态及其新状态,并根据该差异重新渲染组件。

这就是为什么通常不建议直接更新 React 中的状态:

this.state.username = "jamesdoe";
登录后复制

React 将不确定状态是否已更改,并且无法重新渲染组件。

Immutable.js

Redux 遵循不变性的原则。它的 reducer 应该是纯函数,因此它们不应修改当前状态,而应根据当前状态和 action 返回一个新对象。我们通常会像前面那样使用扩展运算符,但是可以使用名为 Immutable.js 的库来实现相同的效果。

虽然纯 JavaScript 可以处理不变性,但在过程中可能会遇到一些陷阱。使用 Immutable.js 保证不变性,同时提供一个性能优越的丰富 API。本文不会详细介绍 Immutability.js 的所有细节,但我们将看一个简单的示例,演示如何在由 React 和 Redux 提供支持的任务应用程序中使用它。

首先,让我们从导入所需的模块并设置 Todo 组件开始。

const { List, Map } = Immutable;
const { Provider, connect } = ReactRedux;
const { createStore } = Redux;
登录后复制

如果在本地机器上操作,则需要安装这些包:

npm install redux react-redux immutable
登录后复制

导入语句如下所示:

import { List, Map } from "immutable";
import { Provider, connect } from "react-redux";
import { createStore } from "redux";
登录后复制

然后,我们可以继续使用一些标记设置我们的 Todo 组件:

// ... Todo 组件代码 ...
登录后复制

我们使用 handleSubmit() 方法创建新的待办事项。在本例中,用户将只创建新的待办事项,我们只需要一个操作:

// ... actions 代码 ...
登录后复制

我们创建的有效负载包含待办事项的 ID 和文本。然后,我们可以继续设置 reducer 函数并将我们上面创建的操作传递给 reducer 函数:

// ... reducer 代码 ...
登录后复制
登录后复制

我们将使用 connect 创建一个容器组件,以便我们可以连接到存储。然后,我们需要传入 mapStateToProps()mapDispatchToProps() 函数来连接。

// ... connect 代码 ...
登录后复制

我们使用 mapStateToProps() 为组件提供存储的数据。然后,我们使用 mapDispatchToProps() 通过将操作绑定到它来使操作创建者作为属性可用于组件。

在 reducer 函数中,我们使用来自 Immutable.js 的 List 来创建应用程序的初始状态。

// ... reducer 代码 ...
登录后复制
登录后复制

List 视为 JavaScript 数组,这就是为什么我们可以在 state 上使用 .push() 方法的原因。用于更新状态的值是一个对象,它继续说明 Map 可以被识别为一个对象。这样,无需使用 Object.assign() 或扩展运算符,因为它保证了当前状态不会改变。这看起来简洁得多,尤其是在状态嵌套得很深的情况下——我们不需要在所有地方都使用扩展运算符。

不变状态使代码能够快速确定是否发生了更改。我们不需要对数据进行递归比较来确定是否发生了更改。也就是说,重要的是要提到,在处理大型数据结构时,您可能会遇到性能问题——复制大型数据对象是有代价的。

但是数据需要更改,因为否则不需要动态站点或应用程序。重要的是如何更改数据。不变性提供了更改应用程序数据(或状态)的正确方法。这使得跟踪状态的更改并确定应用程序的哪些部分应该由于该更改而重新渲染成为可能。

第一次学习不变性会令人困惑。但是,当状态发生变异时,您会遇到弹出的错误,这会让您变得更好。这通常是理解不变性的需求和好处最清晰的方式。

进一步阅读

  • React 和 Redux 中的不变性
  • Immutable.js 101 – Maps 和 Lists
  • 使用 Immutable.js 与 Redux

请注意,由于原文包含大量代码块,为了保持伪原创性并避免过度重复,我简化了一些代码块的描述,并对部分语句进行了同义词替换和句式调整。 图片格式保持不变。

以上是了解JavaScript中的不变性的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

VUE 3 VUE 3 Apr 02, 2025 pm 06:32 PM

它的出局!恭喜Vue团队完成了完成,我知道这是一项巨大的努力,而且很长时间。所有新文档也是如此。

您可以从浏览器获得有效的CSS属性值吗? 您可以从浏览器获得有效的CSS属性值吗? Apr 02, 2025 pm 06:17 PM

我有人写了这个非常合法的问题。 Lea只是在博客上介绍了如何从浏览器中获得有效的CSS属性。那样的是这样。

带有粘性定位的堆叠卡和一点点的杂物 带有粘性定位的堆叠卡和一点点的杂物 Apr 03, 2025 am 10:30 AM

前几天,我发现了科里·金尼文(Corey Ginnivan)网站上的这一点,当您滚动时,彼此之间的卡片堆放集。

在CI/CD上有点 在CI/CD上有点 Apr 02, 2025 pm 06:21 PM

我说的“网站”比“移动应用程序”更合适,但我喜欢Max Lynch的框架:

在WordPress块编辑器中使用Markdown和本地化 在WordPress块编辑器中使用Markdown和本地化 Apr 02, 2025 am 04:27 AM

如果我们需要直接在WordPress编辑器中向用户显示文档,那么最佳方法是什么?

比较浏览器的响应式设计 比较浏览器的响应式设计 Apr 02, 2025 pm 06:25 PM

这些桌面应用程序中有许多目标是同时在不同的维度上显示您的网站。因此,例如,您可以写作

为什么Flex布局中的紫色斜线区域会被误认为是'溢出空间”? 为什么Flex布局中的紫色斜线区域会被误认为是'溢出空间”? Apr 05, 2025 pm 05:51 PM

关于Flex布局中紫色斜线区域的疑问在使用Flex布局时,你可能会遇到一些令人困惑的现象,比如在开发者工具(d...

如何通过CSS选择第一个类名为item的子元素? 如何通过CSS选择第一个类名为item的子元素? Apr 05, 2025 pm 11:24 PM

在元素个数不固定的情况下如何通过CSS选择第一个指定类名的子元素在处理HTML结构时,常常会遇到元素个数不�...

See all articles