搜索
首页web前端css教程了解JavaScript中的不变性

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
@rules具有多少特异性,例如@keyframes和@media?@rules具有多少特异性,例如@keyframes和@media?Apr 18, 2025 am 11:34 AM

前几天我得到了这个问题。我的第一个想法是:奇怪的问题!特异性是关于选择者的,而在符号不是选择器,那么...无关紧要?

您可以嵌套@Media和@support查询吗?您可以嵌套@Media和@support查询吗?Apr 18, 2025 am 11:32 AM

是的,您可以,而且它并不重要。不需要CSS预处理器。它在常规CSS中起作用。

快速吞噬缓存破坏快速吞噬缓存破坏Apr 18, 2025 am 11:23 AM

您应该肯定会在CSS和JavaScript(以及图像和字体以及其他内容)等资产上设置遥远的高速缓存标头。告诉浏览器

寻找可以监视CSS质量和复杂性的堆栈寻找可以监视CSS质量和复杂性的堆栈Apr 18, 2025 am 11:22 AM

许多开发人员写了如何维护CSS代码库的文章,但并没有很多关于如何测量该代码库质量的文章。当然,我们有

数据学家用于建议不执行值的值数据学家用于建议不执行值的值Apr 18, 2025 am 11:08 AM

您是否曾经有一种需要接受简短而任意的文本的表格?喜欢名字或其他。那完全是用的。有很多

苏黎世的最初会议苏黎世的最初会议Apr 18, 2025 am 11:03 AM

我很高兴能前往瑞士苏黎世参加前界(Love the Name and URL!)。我以前从未去过瑞士,所以我很兴奋

使用CloudFlare工人建立全栈无服务器应用程序使用CloudFlare工人建立全栈无服务器应用程序Apr 18, 2025 am 10:58 AM

我在软件开发方面最喜欢的发展之一是无服务器的出现。作为一个倾向于陷入细节的开发人员

在NUXT应用程序中创建动态路由在NUXT应用程序中创建动态路由Apr 18, 2025 am 10:53 AM

在这篇文章中,我们将使用我构建和部署的电子商务商店演示来进行Netlify,以展示如何为传入数据制作动态路线。这是一个公平的

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
1 个月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
1 个月前By尊渡假赌尊渡假赌尊渡假赌
威尔R.E.P.O.有交叉游戏吗?
1 个月前By尊渡假赌尊渡假赌尊渡假赌

热工具

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )专业的PHP集成开发工具

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

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

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器