当前位置: 首页 > news >正文

react的setState中为什么不能用++?

背景:

在使用react的过程中产生了一些困惑,handleClick函数的功能是记录点击次数,handleClick函数被绑定到按钮中,每点击一次将通过this.state.counter将累计的点击次数显示在页面上

image-20240813101737179

困惑:

为什么不能直接写prevState++而是要写成prevState.counter + 1

在React中,setState 方法用于更新组件的状态。当使用函数形式的 setState 时,React 提供了一个函数,该函数接收当前的状态 (prevState) 和当前的属性 (props) 作为参数,并返回一个新状态的对象。这是因为状态的更新应该是不可变的,这意味着不应直接修改现有的状态对象。

# 为什么不能直接写 prevState++

  1. 不可变性:在React中,状态的更新应该遵循不可变原则。直接修改 prevState(如 prevState.count++)会违反这一原则,因为 prevState 是只读的。

  2. 返回值问题prevState.count++ 会立即递增 prevState.count 的值,并返回递增后的值。然而,在 setState 中,你需要返回一个新对象来更新状态,而不是修改 prevState

  3. 状态更新逻辑setState 的目的是更新组件的状态,而不是修改现有状态。使用 prevState.count++ 试图在原有状态上进行修改,这与 setState 的设计目的不符。

正确的做法

正确的做法是返回一个包含更新后状态的新对象。这样可以确保状态的更新是不可变的,并且能够正确地更新组件的状态。以下是正确的示例:

this.setState((prevState) => ({count: prevState.count + 1
}));

React框架源码级解释

为了更好地理解这一点,我们可以看一下React框架中关于 setState 的简化源码示例。请注意,实际的React源码非常复杂,这里提供的代码是为了说明目的而简化过的。

React组件类的简化实现
class ReactComponent {constructor(props) {this.props = props;this.state = {};this._pendingState = null;}setState(partialState, callback) {if (typeof partialState === 'function') {// 当setState接受一个函数时const currentState = this.state;this._pendingState = Object.assign({}, this._pendingState || {}, partialState(currentState));} else {// 当setState接受一个对象时this._pendingState = Object.assign({}, this._pendingState || {}, partialState);}// 触发更新this.scheduleUpdate();}scheduleUpdate() {// 这里模拟React调度更新的逻辑// 在实际的React中,这会触发一系列复杂的更新队列处理// 这里我们只是简单地调用forceUpdatethis.forceUpdate();}forceUpdate(callback) {// 这里模拟React更新组件的逻辑// 在实际的React中,这将触发整个渲染流程this.updateState();if (callback) {callback();}}updateState() {if (this._pendingState) {// 合并pending state到当前状态this.state = Object.assign({}, this.state, this._pendingState);this._pendingState = null;// 重新渲染组件this.render();}}render() {console.log('Rendering component with state:', this.state);// 这里是组件渲染的逻辑// 实际应用中,这会生成虚拟DOM并更新真实DOM}
}
使用简化版React组件

现在我们可以创建一个简单的计数器组件,并使用上面的简化版 setState 方法:

const Counter = (props) => {class CounterComponent extends ReactComponent {constructor(props) {super(props);this.state = { count: 0 };this.handleClick = this.handleClick.bind(this);}handleClick() {this.setState((prevState) => ({count: prevState.count + 1}));}render() {console.log('Rendering counter with state:', this.state);return (<div><p>计数: {this.state.count}</p><button onClick={this.handleClick}>增加计数</button></div>);}}return <CounterComponent />;
};// 创建并渲染组件
const counter = new Counter();
counter.render();

为什么不能使用 prevState++

在上述简化版的实现中,如果你尝试使用 prevState.count++,将会出现问题:

handleClick() {this.setState((prevState) => {const newCount = prevState.count++; // 这里的prevState.count++是不正确的return {count: newCount};});
}

问题在于:

  • prevState 是只读的,不应该直接修改。
  • prevState.count++ 返回的是递增后的值,但这并没有被正确地返回给 setState

总结

在React中,你应该始终使用返回新状态对象的方式来更新状态。这确保了状态更新的不可变性,并且与React的设计理念一致。使用 prevState.count + 1 而不是 prevState.count++ 是正确的做法,因为它遵循了状态更新的最佳实践。

讲讲JS的Object.assign函数?

Object.assign() 是 JavaScript 中的一个方法,用于将所有可枚举的自有属性(own enumerable properties)的值从一个或多个源对象(source objects)复制到目标对象(target object)。如果目标对象中的键与源对象中的键相同,则源对象中的值会覆盖目标对象中的值。

基本语法

Object.assign(target, ...sources)
  • target: 目标对象,所有源对象的属性都会被复制到这个对象上。
  • ...sources: 一个或多个源对象,这些对象的属性会被复制到目标对象上。

示例

下面是一个简单的例子来说明 Object.assign() 的用法:

const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };const result = Object.assign(target, source1, source2);console.log(result); // 输出: { a: 1, b: 2, c: 3 }

在这个例子中,target 对象首先有一个属性 a,然后我们将 source1source2 中的属性合并到 target 上。最终的结果是一个包含了三个属性的对象 { a: 1, b: 2, c: 3 }

注意事项

  1. 浅拷贝Object.assign() 只会复制对象的第一层属性,即它执行的是浅拷贝(shallow copy),不会复制对象内部的嵌套对象。

    const obj1 = { a: 1, b: { x: 10 } };
    const obj2 = { b: { y: 20 }, c: 3 };const mergedObj = Object.assign({}, obj1, obj2);
    console.log(mergedObj); // 输出: { a: 1, b: { y: 20 }, c: 3 }// 修改 obj2 中的嵌套对象会影响 mergedObj
    obj2.b.y = 200;
    console.log(mergedObj.b.y); // 输出: 200
    
  2. 不可枚举属性Object.assign() 不会复制不可枚举的属性(non-enumerable properties)。

  3. 覆盖顺序:如果有相同的属性名,那么后面的源对象的属性值会覆盖前面的源对象的属性值。

  4. 目标对象的改变Object.assign() 默认会修改第一个参数(目标对象),除非你传入一个全新的空对象作为目标对象。

应用场景

在React或其他JavaScript框架中,Object.assign() 经常用来合并对象,特别是在需要基于现有状态创建新状态的情况下。例如,在React中更新组件状态时,通常会这样做:

this.setState(prevState => ({count: Object.assign({}, prevState, { count: prevState.count + 1 })
}));

在这个例子中,prevState 是当前的状态对象,通过 Object.assign 将其与一个新的对象 { count: prevState.count + 1 } 合并,从而创建出一个新的状态对象,其中 count 属性的值被递增了1。

这种方法确保了状态更新是不可变的,这对于保持React应用程序的可预测性和易于调试非常重要。

是的,您提到的 newarr = [...arr1, ...arr2] 是使用数组的扩展运算符(spread operator ...)来合并两个数组。这种做法类似于使用 Object.assign() 来合并对象,但在数组中使用的是扩展运算符而不是 Object.assign()

数组的扩展运算符

扩展运算符 ... 用于将数组或迭代对象展开为独立的元素列表。它可以用于数组、字符串或任何可迭代对象。当用于数组时,扩展运算符可以将一个数组的元素提取出来,就像它们是单独的元素一样。

示例

假设我们有两个数组 arr1arr2,我们可以使用扩展运算符将它们合并为一个新的数组:

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];const newarr = [...arr1, ...arr2];
console.log(newarr); // 输出: [1, 2, 3, 4, 5, 6]

在这个例子中,[...arr1, ...arr2]arr1arr2 的元素提取出来,并将它们合并到一个新的数组 newarr 中。

对比 Object.assign()

对比来看,Object.assign() 用于合并对象。它的工作原理与扩展运算符类似,但针对的是对象而不是数组。

示例

假设我们有两个对象 obj1obj2,我们可以使用 Object.assign() 将它们合并为一个新的对象:

const obj1 = { a: 1 };
const obj2 = { b: 2 };const result = Object.assign({}, obj1, obj2);
console.log(result); // 输出: { a: 1, b: 2 }

在这个例子中,Object.assign({}, obj1, obj2)obj1obj2 的属性合并到一个新的对象中。这里使用了一个空对象 {} 作为目标对象,以避免修改原始对象。

总结

  • 扩展运算符:用于数组和其他可迭代对象,可以将多个数组合并成一个新数组。
  • Object.assign():用于对象,可以将多个对象的属性合并到一个新对象中。

这两种方法都是JavaScript中非常实用的功能,用于创建新数组或对象,同时保持数据的不可变性。在React中,我们通常使用 Object.assign() 来创建新的状态对象,而在其他场景下,扩展运算符则用于数组的操作。

您提到的 Object.assign() 是否复制引用的问题是一个很好的点。确实,Object.assign() 在处理对象时只进行浅拷贝,这意味着如果源对象中包含嵌套的对象,那么这些嵌套对象的引用会被复制到目标对象中,而不是创建新的对象。

浅拷贝 vs. 深拷贝

  • 浅拷贝:只复制对象的第一层属性,对于嵌套的对象,只是复制其引用。
  • 深拷贝:复制对象的所有层级,包括嵌套的对象,创建全新的对象。

示例

让我们通过一个具体的例子来说明这一点:

const obj1 = { a: 1, b: { x: 10 } };
const obj2 = { b: { y: 20 }, c: 3 };const result = Object.assign({}, obj1, obj2);
console.log(result); // 输出: { a: 1, b: { y: 20 }, c: 3 }// 修改 obj2 中的嵌套对象会影响 result
obj2.b.y = 200;
console.log(result.b.y); // 输出: 200

在这个例子中,result 对象包含了来自 obj1obj2 的属性。当 obj2.b.y 的值被修改时,result.b.y 的值也随之改变,因为 result.bobj2.b 是同一个对象的引用。

如何避免这个问题

如果您需要完全独立的对象副本,可以使用深拷贝技术。在JavaScript中,有多种方法可以实现深拷贝,例如使用JSON序列化和反序列化,或者使用第三方库如 lodash_.cloneDeep 方法。

使用JSON序列化和反序列化
const deepClone = (obj) => JSON.parse(JSON.stringify(obj));const obj1 = { a: 1, b: { x: 10 } };
const obj2 = { b: { y: 20 }, c: 3 };const result = Object.assign(deepClone(obj1), obj2);
console.log(result); // 输出: { a: 1, b: { y: 20 }, c: 3 }// 修改 obj2 中的嵌套对象不会影响 result
obj2.b.y = 200;
console.log(result.b.y); // 输出: 20
使用 lodash_.cloneDeep
import _ from 'lodash';const obj1 = { a: 1, b: { x: 10 } };
const obj2 = { b: { y: 20 }, c: 3 };const result = Object.assign(_.cloneDeep(obj1), obj2);
console.log(result); // 输出: { a: 1, b: { y: 20 }, c: 3 }// 修改 obj2 中的嵌套对象不会影响 result
obj2.b.y = 200;
console.log(result.b.y); // 输出: 20

总结

  • Object.assign() 在处理对象时只进行浅拷贝,即对于嵌套的对象,只是复制引用。
  • 如果需要完全独立的对象副本,可以使用深拷贝技术。
  • 使用JSON序列化和反序列化或 lodash_.cloneDeep 方法可以实现深拷贝。

希望这些解释和示例有助于澄清 Object.assign() 的行为以及如何处理对象的拷贝问题。如果您还有其他疑问或需要进一步的帮助,请随时提问。

是的,您的理解是正确的。当我们使用 Object.assign() 来合并 obj1obj2 时,obj2 中的属性会覆盖 obj1 中相同名称的属性。对于嵌套对象,obj2 中的嵌套对象会覆盖 obj1 中相同名称的嵌套对象。

在您给出的例子中,obj1obj2 分别如下:

const obj1 = { a: 1, b: { x: 10 }, c: 5 };
const obj2 = { b: { y: 20 }, c: 3 };

当我们使用 Object.assign() 来合并这两个对象时,obj2 中的属性会覆盖 obj1 中的相应属性。因此,bc 属性会被 obj2 中的值覆盖。结果将是:

const result = Object.assign(obj1, obj2);
console.log(result); // 输出: { a: 1, b: { y: 20 }, c: 3 }

这里发生了以下几件事:

  1. obj1 中的 a 属性没有被覆盖,因此保留原样。
  2. obj1 中的 b 属性被 obj2 中的 b 属性覆盖。这意味着 obj1 中的 { x: 10 } 被替换为 obj2 中的 { y: 20 }
  3. obj1 中的 c 属性被 obj2 中的 c 属性覆盖,5 被替换为 3

最终的 result 对象将是 { a: 1, b: { y: 20 }, c: 3 }

请注意,由于 Object.assign() 默认修改第一个参数(在这里是 obj1),所以在这种情况下,obj1 也被修改成了 { a: 1, b: { y: 20 }, c: 3 }。如果您希望创建一个新的对象而不是修改 obj1,可以使用一个空对象作为目标对象,如下所示:

const result = Object.assign({}, obj1, obj2);
console.log(result); // 输出: { a: 1, b: { y: 20 }, c: 3 }

这样,obj1 保持不变,而 result 是一个新的对象。

当使用 Object.assign() 合并对象时,对于嵌套的对象,Object.assign() 只会复制引用,而不是创建新的对象。这意味着如果原对象和合并后的对象都包含对同一个嵌套对象的引用,那么对其中一个对象的修改会影响到另一个对象。

让我们通过一个具体的例子来说明这一点:

const obj1 = { a: 1, b: { x: 10 }, c: 5 };
const obj2 = { b: { y: 20 }, c: 3 };const result = Object.assign(obj1, obj2);
console.log(result); // 输出: { a: 1, b: { y: 20 }, c: 3 }// 修改 obj2 中的嵌套对象会影响 result
obj2.b.z = 30;
console.log(result.b); // 输出: { y: 20, z: 30 }

在这个例子中,resultobj2 都包含了对同一个嵌套对象的引用。当我们修改 obj2.b 添加一个新属性 z 时,result.b 也反映了这个变化,因为它们都指向同一个对象。

示例代码

下面是完整的示例代码:

const obj1 = { a: 1, b: { x: 10 }, c: 5 };
const obj2 = { b: { y: 20 }, c: 3 };const result = Object.assign(obj1, obj2);
console.log(result); // 输出: { a: 1, b: { y: 20 }, c: 3 }// 修改 obj2 中的嵌套对象会影响 result
obj2.b.z = 30;
console.log(result.b); // 输出: { y: 20, z: 30 }

总结

  • Object.assign() 在处理嵌套对象时只复制引用,而不是创建新的对象。
  • 因此,如果两个对象包含对同一个嵌套对象的引用,那么对其中一个对象的修改会影响到另一个对象。
  • 如果需要完全独立的对象副本,可以使用深拷贝技术,例如使用JSON序列化和反序列化或使用 lodash_.cloneDeep 方法。

相关文章:

react的setState中为什么不能用++?

背景&#xff1a; 在使用react的过程中产生了一些困惑&#xff0c;handleClick函数的功能是记录点击次数&#xff0c;handleClick函数被绑定到按钮中&#xff0c;每点击一次将通过this.state.counter将累计的点击次数显示在页面上 困惑&#xff1a; 为什么不能直接写prevStat…...

2.2算法的时间复杂度与空间复杂度——经典OJ

本博客的OJ标题均已插入超链接&#xff0c;点击可直接跳转~ 一、消失的数字 1、题目描述 数组nums包含从0到n的所有整数&#xff0c;但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗&#xff1f; 2、题目分析 &#xff08;1&#xff09;numsS…...

【CentOS 】DHCP 更改为静态 IP 地址并且遇到无法联网

文章目录 引言解决方式标题1. **编辑网络配置文件**&#xff1a;标题2. **确保配置文件包含以下内容**&#xff1a;特别注意 标题3. **重启网络服务**&#xff1a;标题4. **检查配置是否生效**&#xff1a;标题5. **测试网络连接**&#xff1a;标题6. **检查路由表**&#xff1…...

Linux 操作系统 --- 信号

序言 在本篇内容中&#xff0c;将为大家介绍在操作系统中的一个重要的机制 — 信号。大家可能感到疑惑&#xff0c;好像我在使用 Linux 的过程中并没有接触过信号&#xff0c;这是啥呀&#xff1f;其实我们经常遇到过&#xff0c;当我们运行的进程当进程尝试访问非法内存地址时…...

黑马前端——days09_css

案例 1 页面框架文件 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv"X-UA-Compati…...

【Python爬虫】技术深度探索与实践

目录 引言 第一部分&#xff1a;Python爬虫基础 1.1 网络基础 1.2 Python爬虫基本流程 第二部分&#xff1a;进阶技术 2.1 动态网页抓取 2.2 异步编程与并发 2.3 反爬虫机制与应对 第三部分&#xff1a;实践案例 第四部分&#xff1a;法律与道德考量 第五部分&#x…...

智启万象|挖掘广告变现潜力,保障支付安全便捷

谷歌致力于为开发者提供 先进的广告变现与支付解决方案 一起回顾 2024 Google 开发者大会 了解如何利用谷歌最新工具和功能 提高变现收入&#xff0c;优化用户体验&#xff0c;保障交易安全 让变现更上一层楼 广告检查器是谷歌 AdMob 平台最新推出的高级测试工具&#xff0c;开…...

函数递归,匿名、内置行数,模块和包,开发规范

一、递归与二分法 一&#xff09;递归 1、递归调用的定义 递归调用&#xff1a;在调用一个函数的过程中&#xff0c;直接或间接地调用了函数本身 2、递归分为两类&#xff1a;直接与间接 #直接 def func():print(from func)func()func() # 间接 def foo():print(from foo)bar…...

Springboot3 整合swagger

一、pom.xml <dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-starter-webmvc-api</artifactId><version>2.1.0</version></dependency> 二、application.yml # SpringDoc配置 # springdoc:swa…...

查看同一网段内所有设备的ip

使用命令提示符&#xff08;CMD&#xff09;进行扫描 查看本机IP地址 首先通过 ipconfig /all 命令查看本机的IP地址&#xff0c;确定你的网段&#xff0c;例如 192.168.1.。 Ping网段内每个IP地址 接着使用循环命令&#xff1a; for /L %i IN (1,1,254) DO ping -w 1 -n …...

Spark MLlib 特征工程(上)

文章目录 Spark MLlib 特征工程(上)特征工程预处理 Encoding:StringIndexer特征构建:VectorAssembler特征选择:ChiSqSelector归一化:MinMaxScaler模型训练总结Spark MLlib 特征工程(上) 前面我们一起构建了一个简单的线性回归模型,来预测美国爱荷华州的房价。从模型效果来…...

《SPSS零基础入门教程》学习笔记——03.变量的统计描述

文章目录 3.1 连续变量&#xff08;1&#xff09;集中趋势&#xff08;2&#xff09;离散趋势&#xff08;3&#xff09;分布特征 3.2 分类变量&#xff08;1&#xff09;单个分类变量&#xff08;2&#xff09;多个分类变量 3.1 连续变量 &#xff08;1&#xff09;集中趋势 …...

2024年杭州市网络与信息安全管理员(网络安全管理员)职业技能竞赛的通知

2024年杭州市网络与信息安全管理员&#xff08;网络安全管理员&#xff09;职业技能竞赛的通知 一、组织机构 本次竞赛由杭州市总工会牵头&#xff0c;杭州市人力资源和社会保障局联合主办&#xff0c;杭州市萧山区总工会承办&#xff0c;浙江省北大信息技术高等研究院协办。…...

SpringBoot参数校验详解

前言 在web开发时&#xff0c;对于请求参数&#xff0c;一般上都需要进行参数合法性校验的&#xff0c;原先的写法时一个个字段一个个去判断&#xff0c;这种方式太不通用了&#xff0c;Hibernate Validator 是 Bean Validation 规范的参考实现&#xff0c;用于在 Java 应用中…...

安全基础学习-SHA-1(Secure Hash Algorithm 1)算法

SHA-1(Secure Hash Algorithm 1)是一种密码学哈希函数,用于将任意长度的输入数据(消息)转换成一个固定长度的输出(哈希值或摘要),长度为160位(20字节)。SHA-1的主要用途包括数据完整性验证、数字签名、密码存储等。 1、SHA-1 的特性 定长输出:无论输入数据长度是多…...

leetcode350. 两个数组的交集 II,哈希表

leetcode350. 两个数组的交集 II 给你两个整数数组 nums1 和 nums2 &#xff0c;请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数&#xff0c;应与元素在两个数组中都出现的次数一致&#xff08;如果出现次数不一致&#xff0c;则考虑取较小值&#xff09;。可…...

基于YOLOv8的缺陷检测任务模型训练

文章目录 一、引言二、环境说明三、缺陷检测任务模型训练详解3.1 PCB数据集3.1.1 数据集简介3.1.2 数据集下载3.1.3 构建yolo格式的数据集 3.2 基于ultralytics训练YOLOv83.2.1 安装依赖包3.2.2 ultralytics的训练规范说明3.2.3 创建训练配置文件3.2.4 下载预训练模型3.2.5 训练…...

【upload]-ini-[SUCTF 2019]CheckIn-笔记

上传图片木马文件后看到&#xff0c;检查的文件内容&#xff0c;包含<? 一句话木马提示 检查的文件格式 用如下图片木马&#xff0c;加上GIF89a绕过图片和<?检查 GIF89a <script languagephp>eval($_POST[cmd])</script> .user.ini实际上就是一个可以由用…...

uniapp条件编译使用教学(#ifdef、#ifndef)

#ifdef //仅在xxx平台使用#ifndef //除了在xxx平台使用#endif // 结束 标识平台APP-PLUSAPPMP微信小程序/支付宝小程序/百度小程序/头条小程序/QQ小程序MP-WEIXIN微信小程序MP-ALIPAY支付宝小程序MP-BAIDU百度小程序MP-TOUTIAO头条小程序MP-QQQQ小程序H5H5APP-PLUS-NVUEApp nv…...

NXP i.MX8系列平台开发讲解 - 4.1.2 GNSS 篇(二) - 卫星导航定位原理

专栏文章目录传送门&#xff1a;返回专栏目录 Hi, 我是你们的老朋友&#xff0c;主要专注于嵌入式软件开发&#xff0c;有兴趣不要忘记点击关注【码思途远】 文章目录 关注星号公众号&#xff0c;不容错过精彩 作者&#xff1a;HywelStar Hi, 我是你们的老朋友HywelStar, 根…...

怎样在 SQL 中对一个包含销售数据的表按照销售额进行降序排序?

在当今数字化商业的浪潮中&#xff0c;数据就是企业的宝贵资产。对于销售数据的有效管理和分析&#xff0c;能够为企业的决策提供关键的支持。而在 SQL 中&#xff0c;对销售数据按照销售额进行降序排序&#xff0c;是一项基础但极其重要的操作。 想象一下&#xff0c;您面前有…...

DIAdem 与 LabVIEW

DIAdem 和 LabVIEW 都是 NI (National Instruments) 公司开发的产品&#xff0c;尽管它们有不同的核心功能和用途&#xff0c;但它们在工程、测试和测量领域中常常一起使用&#xff0c;以形成一个完整的数据采集、分析、处理和报告生成的解决方案。 1. 功能和用途 LabVIEW (Lab…...

UE虚幻引擎可以云渲染吗?应用趋势与挑战了解

虚幻云渲染技术是基于虚幻引擎的云端渲染技术&#xff0c;将虚幻引擎的渲染计算任务通过云计算的方式进行处理和渲染、并将渲染结果传输到终端设备上进行展示。虚幻引擎云渲染技术在近年来得到了迅猛的发展&#xff0c;并在各个领域得到了广泛的应用&#xff0c;包括游戏、电影…...

实战分享:DefenderUI在企业环境中的部署与应用

前言 想象一下&#xff0c;你的电脑就像一座坚固的城堡&#xff0c;但城门却时常被一些不速之客窥探甚至企图入侵&#xff1b;Defender&#xff0c;作为城堡自带的守护者&#xff0c;实力自然不容小觑&#xff1b;但你是否觉得它有时候太过低调&#xff0c;有些隐藏技能还没完…...

中英双语介绍金融经济中的鹰派 (Hawkish)和鸽派 (Dovish)

中文版 在金融和经济政策中&#xff0c;“鹰派”和“鸽派”是两种对货币政策和经济管理有不同立场的群体。 鹰派 (Hawkish) 鹰派倾向于担心通货膨胀的风险&#xff0c;通常支持较高的利率和更紧的货币政策&#xff0c;以防止经济过热和控制物价上涨。具体特征包括&#xff1…...

Android 开发中常用的布局类型及其选择指南

在 Android 开发过程中,选择正确的布局类型对于构建高效、美观且响应式的用户界面至关重要。本文将介绍 Android 中几种最常用的布局类型,并对比它们的特点和适用场景,帮助开发者们做出明智的选择。 1. LinearLayout - 线性布局 特点: LinearLayout 是最基本的布局类型之一…...

短视频SDK解决方案,降低行业开发门槛

美摄科技匠心打造了一款集前沿技术与极致体验于一体的短视频SDK解决方案&#xff0c;它不仅重新定义了短视频创作的边界&#xff0c;更以行业标杆级的短视频特效&#xff0c;让每一帧画面都闪耀不凡光芒。 【技术赋能&#xff0c;创意无限】 美摄科技的短视频SDK&#xff0c;…...

【C++】String常见函数用法

一、string类对象的常见构造 我们可采取以下的方式进行构造&#xff0c;以下是常用的接口&#xff1a; //生成空字符串 string; //拷贝构造函数 string(const string& str); //用C-string来构造string类对象 string(const char* s); //string类对象中包含n个字符c strin…...

LeetCode49.字母异位词分组

题目大意 给你一个字符串数组&#xff0c;请你将字母异位词组合在一起。可以按任意顺序返回结果列表。 字母异位词是由重新排列源单词的所有字母得到的一个新单词。 思路分析 示例 1: 输入: strs ["eat", "tea", "tan", "ate", &…...

Nginx日志按天分割

需求、日志按照天的单位进行分割存储。 如果你直接百度&#xff0c;可能会搜到很多教你用各种脚本或是三方插件来按天分割的&#xff0c;这边我用nginx服务本身来分割日志。 方法一 通过使用 $time_iso8601 变量和 map 指令&#xff0c;实现了日志文件按天分割的功能。以下是…...

文本摘要简介

文本摘要是从一段长文本中提取出最重要的信息&#xff0c;并生成一个简短而有意义的摘要。这个过程可以分为两种主要方法&#xff1a; 抽取式摘要&#xff08;Extractive Summarization&#xff09;&#xff1a;从原文中直接提取出关键句子或段落&#xff0c;组成摘要…...

3.MySQL面试题之Redis 和 Mysql 如何保证数据一致性?

Redis 和 MySQL 数据一致性是分布式系统中的一个常见挑战。保证数据一致性通常涉及几种策略&#xff0c;我会详细解释这些策略并提供相应的代码示例。 先更新数据库&#xff0c;再更新缓存 这种方法先更新 MySQL&#xff0c;然后更新或删除 Redis 缓存。 Transactional publ…...

浅谈TCP协议、UDP协议

一、介绍说明 TCP&#xff08;传输控制协议&#xff09; 面向连接&#xff1a;TCP在数据传输之前必须建立连接。这通过一个称为三次握手的过程来完成&#xff0c;确保连接的两端都准备好进行数据传输。 可靠性&#xff1a;TCP提供可靠的数据传输&#xff0c;确保数据包正确无…...

SQL业务题: 从不订购的客户

1️⃣题目 Customers 表&#xff1a; ---------------------- | Column Name | Type | ---------------------- | id | int | | name | varchar | ---------------------- 在 SQL 中&#xff0c;id 是该表的主键。 该表的每一行都表示客户的 ID 和名…...

怎么直接在PDF上修改内容?随心编辑PDF内容

PDF(Portable Document Format)作为一种专用于阅读而非编辑的文档格式&#xff0c;其设计的核心目的是保持文档格式的一致性&#xff0c;确保文档在不同平台和设备上都能以相同的布局和格式呈现。然而&#xff0c;在实际工作和生活中&#xff0c;我们经常需要对PDF文档进行编辑…...

聊天室项目测试报告

项目介绍 本项目是一个基于Spring Boot框架开发的聊天室应用。一个实时的文本消息交流平台&#xff0c;允许多个用户同时在线聊天。系统采用了Spring Boot作为后端框架&#xff0c;集成了WebSocket技术以实现消息的实时推送与接收提供一个简单、易用且功能完备的在线聊天环境。…...

语音识别(实时语音转录)——funasr的详细部署和使用教程(包括实时语音转录)

阿里达摩院开源大型端到端语音识别工具包FunASR&#xff1a; FunASR提供了在大规模工业语料库上训练的模型&#xff0c;并能够将其部署到应用程序中。工具包的核心模型是Paraformer&#xff0c;这是一个非自回归的端到端语音识别模型&#xff0c;经过手动注释的普通话语音识别…...

【网络编程】TCP机械臂测试

通过w(红色臂角度增大)s&#xff08;红色臂角度减小&#xff09;d&#xff08;蓝色臂角度增大&#xff09;a&#xff08;蓝色臂角度减小&#xff09;按键控制机械臂 注意&#xff1a;关闭计算机的杀毒软件&#xff0c;电脑管家&#xff0c;防火墙 1&#xff09;基于TCP服务器…...

笔记:在WPF中如何注册控件级全局事件和应用程序级全局事件

一、目的&#xff1a;在WPF中如何注册控件级全局事件和应用程序级全局事件 二、实现 应用程序级全局事件 //注册应用程序级全局事件 EventManager.RegisterClassHandler(typeof(Button), Button.ClickEvent, new RoutedEventHandler(ic_event_Click)); 如上代码既会注册全局…...

【Linux系列】telnet使用入门

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

音视频相关知识

H.264编码格式 音频 PCM就是要把声音从模拟信号转换成数字信号的一种技术&#xff0c;他的原理简单地说就是利用一个固定的频率对模拟信号进行采样。 pcm是无损音频音频文件格式...

数据结构--第七天

递归 -递归的概念 递归其实就是一种解决问题的办法&#xff0c;在C语言中&#xff1a;递归就是函数自己调用自己 -递归的思想 递归的思考方式就是把大事化小的过程 递归的递就是递推的意思&#xff0c;归就是回归的意思 &#xff08;递归是少量的代码完成大量的运算&#xff09…...

代码随想录Day34:62.不同路径、63.不同路径II、343.整数拆分、96.不同的二叉搜索树

62. 不同路径 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少条不同的路径&…...

【信息学奥赛一本通】1008:计算(a+b)/c的值

1008&#xff1a;计算(ab)/c的值 时间限制: 1000 ms 内存限制: 66536 KB 提交数:164836 通过数: 142434 【题目描述】 给定3个整数a、b、c&#xff0c;计算表达式abc的值。 【输入】 输入仅一行&#xff0c;包括三个整数a、b、c, 数与数之间以一个空格分开。(&#xff0d;10,…...

使用 jstat 进行 Java 应用程序性能监控

jstat 使用经验笔记 1. 简介 jstat 是 Java 开发工具包 (JDK) 中的一个命令行工具&#xff0c;用于监控 Java 虚拟机 (JVM) 的运行时状态&#xff0c;特别是垃圾回收 (Garbage Collection, GC) 的行为。通过使用 jstat&#xff0c;你可以监控和诊断 Java 应用程序的内存使用情…...

Prompt指令调优大揭秘

Hey&#xff0c;技术达人们&#xff01;今天咱们就来聊聊Prompt指令调优的那些事儿。想象一下&#xff0c;你有一个超级智能的AI小伙伴&#xff0c;但要让它更懂你&#xff0c;更给力&#xff0c;那就得靠点“魔法”——Prompt指令调优。准备好了吗&#xff1f;让我们一探究竟&…...

C语言中的⽂件操作

1. 为什么使⽤⽂件&#xff1f; 如果没有⽂件&#xff0c;我们写的程序的数据是存储在电脑的内存中&#xff0c;如果程序退出&#xff0c;内存回收&#xff0c;数据就丢失了&#xff0c;等再次运⾏程序&#xff0c;是看不到上次程序的数据的&#xff0c;如果要将数据进⾏持久化…...

黑马前端——days14_js

案例 1 页面框架文件 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title>&l…...

【自动驾驶】ROS中参数服务器通信(c++)

目录 通信过程新建参数服务器包编写测试文件修改cmakelist:搭配launch文件启动测试及结果 通信过程 1.Talker 设置参数 Talker 通过 RPC 向参数服务器发送参数(包括参数名与参数值)&#xff0c;ROS Master 将参数保存到参数列表中。 2.Listener 获取参数 Listener 通过 RPC 向…...

零基础5分钟上手亚马逊云科技核心云开发知识 - 网络基础

简介&#xff1a; 欢迎来到小李哥全新亚马逊云科技AWS云计算知识学习系列&#xff0c;适用于任何无云计算或者亚马逊云科技技术背景的开发者&#xff0c;通过这篇文章大家零基础5分钟就能完全学会亚马逊云科技一个经典的服务开发架构方案。 我会每天介绍一个基于亚马逊云科技…...