”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > JavaScript 函数式编程简介:镜头#9

JavaScript 函数式编程简介:镜头#9

发布于2024-08-06
浏览:506

Introduction to Functional Programming in JavaScript: Lenses #9

镜头是一种强大而优雅的方式,可以在函数式编程中关注和操作部分不可变数据结构。它们提供了一种在嵌套对象或数组中获取和设置值的机制,而无需改变原始数据。

什么是镜头?

镜头是一流的抽象,它提供了一种访问和更新数据结构各部分的方法。透镜通常由两个函数定义:getter 和 setter。

  • Getter:从数据结构中提取值的函数。
  • Setter:更新数据结构中的值并返回该结构的新副本的函数。

镜头对于处理不可变数据结构特别有用,因为它们允许在不改变原始数据的情况下进行更改。

镜片的优点

  1. 不变性:镜头有助于处理不可变的数据结构,确保原始数据不被修改。
  2. 模块化:镜头允许您模块化数据访问和更新,使您的代码更可重用且更易于维护。
  3. 可组合性:可以组合镜头以专注于数据结构的嵌套部分,从而将复杂的数据操作分解为更简单的可组合操作。

在 JavaScript 中实现镜头

让我们从 JavaScript 中镜头的基本实现开始。

基本镜头实现

镜头可以通过 get 和 set 方法实现为对象。

const lens = (getter, setter) => ({
  get: (obj) => getter(obj),
  set: (val, obj) => setter(val, obj),
});

const prop = (key) => lens(
  (obj) => obj[key],
  (val, obj) => ({ ...obj, [key]: val })
);

// Usage
const user = { name: 'Alice', age: 30 };

const nameLens = prop('name');

const userName = nameLens.get(user);
console.log(userName); // 'Alice'

const updatedUser = nameLens.set('Bob', user);
console.log(updatedUser); // { name: 'Bob', age: 30 }

在此示例中,prop 创建一个聚焦于对象的特定属性的镜头。 get 方法检索属性的值,set 方法更新该值并返回一个新对象。

构图镜头

可以组合镜头来处理嵌套数据结构。在这里,我们将创建一个实用程序来组合镜头。

const composeLenses = (outerLens, innerLens) => ({
  get: (obj) => innerLens.get(outerLens.get(obj)),
  set: (val, obj) => outerLens.set(innerLens.set(val, outerLens.get(obj)), obj),
});

// Usage with nested data
const addressLens = prop('address');
const cityLens = prop('city');

const userAddressCityLens = composeLenses(addressLens, cityLens);

const user = {
  name: 'Alice',
  address: {
    city: 'Wonderland',
    zip: '12345',
  },
};

const userCity = userAddressCityLens.get(user);
console.log(userCity); // 'Wonderland'

const updatedUser = userAddressCityLens.set('Oz', user);
console.log(updatedUser); // { name: 'Alice', address: { city: 'Oz', zip: '12345' } }

在此示例中,composeLenses 允许我们创建一个专注于地址对象内的城市属性的镜头。这使得能够以模块化和可重用的方式访问和更新嵌套属性。

镜头的实际应用

镜头在不变性和模块化数据操作很重要的场景中特别有用,例如前端应用程序的状态管理。

在 React 中管理状态

在 React 应用程序中,镜头可用于以更实用且可预测的方式管理状态更新。

import React, { useState } from 'react';

const App = () => {
  const [state, setState] = useState({
    user: {
      name: 'Alice',
      address: {
        city: 'Wonderland',
      },
    },
  });

  const userLens = prop('user');
  const addressLens = prop('address');
  const cityLens = prop('city');

  const userAddressCityLens = composeLenses(userLens, composeLenses(addressLens, cityLens));

  const updateCity = (newCity) => {
    const newState = userAddressCityLens.set(newCity, state);
    setState(newState);
  };

  return (
    

City: {userAddressCityLens.get(state)}

); }; export default App;

在此示例中,我们使用镜头来模块化 React 组件状态中嵌套城市属性的访问和更新。这种方法使状态更新更可预测且更易于管理。

版本声明 本文转载于:https://dev.to/francescoagati/introduction-to-functional-programming-in-javascript-lenses-9-3217?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 可以在纯CS中将多个粘性元素彼此堆叠在一起吗?
    可以在纯CS中将多个粘性元素彼此堆叠在一起吗?
    </main> <section> ,但无法使其正常工作,如您所见。任何洞察力都将不胜感激! display:grid; { position:sticky; top:1em; z-index:1 1 ; { { { pos...
    编程 发布于2025-02-07
  • 如何在Java中获取当前的UTC/GMT日期和时间?
    如何在Java中获取当前的UTC/GMT日期和时间?
    如何在Java中的UTC或GMT中获取当前日期和时间?即时类代表时间表上的特定时刻在UTC中具有纳秒精度。要将此瞬间转换为更易读的字符串表示形式,您可以使用toString()方法: instant.now()。 2016-09-13T23:30:52.123Z 注意:在Java 8之前,Jav...
    编程 发布于2025-02-07
  • 背景线程如何阻止在长期运行过程中winforms应用中的UI冻结?
    背景线程如何阻止在长期运行过程中winforms应用中的UI冻结?
    [2 防止winforms ui用背景线程冻结了长期运行的操作 Winforms应用程序中的长期运行,尤其是使用 此方法保持UI响应能力,从而显着改善了用户体验。 .NET提供了几种管理背景线程的机制,每个机制都提供不同的控制级别: 线程管理选项。 threadpool.queueuserwo...
    编程 发布于2025-02-07
  • Objectaid UML Explorer如何帮助您从Java代码生成UML图?
    Objectaid UML Explorer如何帮助您从Java代码生成UML图?
    从Java代码生成UML图:一种综合方法此工具在现有代码中无缝运行,消除了反向反向的需求工程。关键功能包括:实时图更新代码中的更改,确保连续对齐。自动图与源代码和库更新。与重构操作的无缝集成,确保图表与代码修改保持同步。跨工作区的全局图更新,自动从版本控制中查看必要的图表以进行进一步的对齐。 ,在...
    编程 发布于2025-02-07
  • 如何在JavaScript对象中动态设置键?
    如何在JavaScript对象中动态设置键?
    如何为JavaScript对象变量创建动态键,尝试为JavaScript对象创建动态键,使用此Syntax jsObj['key' i] = 'example' 1;将不起作用。正确的方法采用方括号:他们维持一个长度属性,该属性反映了数字属性(索引)和一个数字属性的数量。标准对象没有模仿这...
    编程 发布于2025-02-07
  • 为什么我会得到\“ attributeError:module \'enum \'没有属性\'intflag \'\” python 3.6.1?
    为什么我会得到\“ attributeError:module \'enum \'没有属性\'intflag \'\” python 3.6.1?
    [ attributeError:module'enum'在python 3.6.1 一个可能的原因是Enum34软件包的存在,该软件包提供了与Python 3.4和更早版本的兼容性。但是,在Python 3.6及以后的情况下,不再需要Enum34的实现。要验证ENUM34是否正...
    编程 发布于2025-02-07
  • 如何使用Python的记录模块实现自定义处理?
    如何使用Python的记录模块实现自定义处理?
    使用Python的Loggging Module 确保正确处理和登录对于疑虑和维护的稳定性至关重要Python应用程序。尽管手动捕获和记录异常是一种可行的方法,但它可能乏味且容易出错。解决此问题,Python允许您覆盖默认的异常处理机制,并将其重定向为登录模块。这提供了一种方便而系统的方法来捕获和...
    编程 发布于2025-02-07
  • 操作员?= Java脚本
    操作员?= Java脚本
    JavaScript 的安全赋值运算符 ?=:简化异步操作中的错误处理 JavaScript 引入了一个新的运算符 ?=,称为安全赋值运算符。它旨在简化代码中的错误处理,使代码更易于阅读和维护,尤其是在处理 try-catch 错误捕获函数时。 ?= 运算符如何工作? 使用 ?= 运算符时,它会检...
    编程 发布于2025-02-07
  • 在保持其内容完整时,如何删除DIV元素?
    在保持其内容完整时,如何删除DIV元素?
    在保留其元素 display:cottents; display:cottents; cottents;在这种情况下是理想的选择。它导致元素的孩子出现为父母的直接子女,无视元素本身。当使用CSS网格或其他应该忽略包装元素的布局技术时,这是有价值的。 。容器{ 显示:Flex; } 。一 {...
    编程 发布于2025-02-07
  • 在JavaScript中声明变量时,为什么要始终使用\“ var \”?
    在JavaScript中声明变量时,为什么要始终使用\“ var \”?
    考虑以下示例:您可能希望此功能返回11;但是,由于“ varaible2 = 6”上的错别字,它返回了NAN。线。更糟糕的是,该错别字无意间创建一个全局变量,它具有拼写错误的名称“ varaible2。因此,强烈建议使用“ var”关键字,即使对于全局变量,也建议始终使用“ var”关键字来声明变...
    编程 发布于2025-02-06
  • 如何从大熊猫的大型文本数据集中有效删除标点符号?
    如何从大熊猫的大型文本数据集中有效删除标点符号?
    挑战: 这个问题在处理大型文本数据集时探索了str.replace的几种性能替代方案: 1。 REGEX.SUB:使用预编译的Regex模式从RE库中使用SUB函数。此方法对str.replace进行了重大的性能改进。 2。 str.translate:利用python的str.transla...
    编程 发布于2025-02-06
  • 为什么使用Firefox后退按钮时JavaScript执行停止?
    为什么使用Firefox后退按钮时JavaScript执行停止?
    导航历史记录问题:JavaScript使用Firefox Back Back 此行为是由浏览器缓存JavaScript资源引起的。 To resolve this issue and ensure scripts execute on subsequent page visits, Firefox...
    编程 发布于2025-02-06
  • 我如何设计用于存储全球街道地址的最佳数据库?
    我如何设计用于存储全球街道地址的最佳数据库?
    确定全球街道地址的最佳数据库设计作为程序员,您会面临设计数据库的挑战来自世界各地。本文探讨了实现此目标的可能性,并提供了一种实用方法。 全局地址的常见数据库结构地址line(x4) 邮政编码 sub-building house/premise number 简化数据输入局部考虑[&&&&&&&...
    编程 发布于2025-02-06
  • 我可以将加密从McRypt迁移到OpenSSL,并使用OpenSSL迁移MCRYPT加密数据?
    我可以将加密从McRypt迁移到OpenSSL,并使用OpenSSL迁移MCRYPT加密数据?
    将我的加密库从mcrypt升级到openssl 问题:是否可以将我的加密库从McRypt升级到OpenSSL?如果是这样?使用openssl?答案:可以使用mcrypt数据加密数据,可以使用openssl。关于如何使用openssl对McRypt进行加密的数据: openssl_decrypt...
    编程 发布于2025-02-06
  • 如何在Java列表中有效计算元素的发生?
    如何在Java列表中有效计算元素的发生?
    计数列表中的元素出现在列表 中,在java编程中,列举列表中列举元素出现的任务来自列表。为此,收集框架提供了全面的工具套件。在这种情况下,Batocurrences变量将保持值3,代表动物列表中的“ BAT”出现的数量。 &&& [此方法是简单的,可以得出准确的结果,使其成为计算列表中元素出现的理...
    编程 发布于2025-02-06

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3