TypeScript学习笔记(二)——TypeScript 高级类型

news2024/11/14 15:43:52

目录

1. class 类

1.1 class 关键字的基本使用

1.2 类继承

1.3 类成员可见性

1.4 类成员只读修饰符

2. 类型兼容性

2.1 类型兼容性

2.2 接口兼容性

2.3 函数兼容性

3. 交叉类型

4. 泛型

4.1 创建泛型函数

4.2 泛型约束

4.3 多个泛型的类型变量约束

4.4 泛型接口

4.5 泛型类

4.6 泛型工具类型

① 泛型工具类型 - Partial

② 泛型工具类型 - Readonly

③ 泛型工具类型 - Pick,>

④ 泛型工具类型 - Record,type>

5. 索引签名类型

6. 映射类型


概述:

  • TS 中的高级类型有很多,重点学习以下高级类型:
    • 1. class 类
    • 2. 类型兼容性
    • 3. 交叉类型
    • 4. 泛型 和 keyof
    • 5. 索引签名类型 和 索引查询类型
    • 6. 映射类型

1. class 类

1.1 class 关键字的基本使用

TypeScript 全面支持 ES2015 中引入的 class 关键字,并为其添加了类型注解和其他语法(比如,可见性修饰符等)。
解释:
  • 根据 TS 中的类型推论,可以知道 Person 类的实例对象 p 的类型是 Person。
  • TS 中的 class不仅提供了 class 的语法功能,也作为一种类型存在
实例属性初始化:
解释:
  • 声明成员 age,类型为 number(没有初始值)。
  • 声明成员 gender,并设置初始值,此时,可省略类型注解(TS 类型推论 为 string 类型)。
构造函数:
解释:
  • 成员初始化(比如,age: number)后,才可以通过 this.age 来访问实例成员。
  • 需要为构造函数指定类型注解,否则会被隐式推断为 any;构造函数不需要返回值类型。
实例方法:
解释:
  • 方法的类型注解(参数和返回值)与函数用法相同。

1.2 类继承

类继承的两种方式:
  • extends(继承父类)
  • implements(实现接口)
说明:
  • JS 中只有 extends,而 implements 是 TS 提供的。

① extends(继承父类)

解释:
  • 通过 extends 关键字实现继承
  • 子类 Dog 继承父类 Animal,则 Dog 的实例对象 dog 就同时具有了父类 Animal 和 子类 Dog 的所有属性和方法。

② implements(实现接口)

解释:
  • 通过 implements 关键字让 class 实现接口。
  • Person 类实现接口 Singable 意味着,Person 类中必须提供 Singable 接口中指定的所有方法和属性。

1.3 类成员可见性

类成员可见性:
  • 可以使用 TS 来控制 class 的方法或属性对于 class 外的代码是否可见
可见性修饰符包括:
  • public(公有的)
  • protected(受保护的)
  • private(私有的)。
①  public(公有的)
  • public:表示公有的、公开的,公有成员可以被任何地方访问,默认可见性。
解释:
  • 在类属性或方法前面添加 public 关键字,来修饰该属性或方法是共有的。
  • 因为 public 是默认可见性,所以,可以直接省略

② protected(受保护的)

  • protected:表示受保护的,仅对其声明所在类和子类中(非实例对象)可见。

解释:
  • 在类属性或方法前面添加 protected 关键字,来修饰该属性或方法是受保护的。
  • 在子类的方法内部可以通过 this 来访问父类中受保护的成员,但是,对实例不可见

③ private(私有的)

  • private:表示私有的只在当前类中可见,对实例对象以及子类也是不可见的。

解释:
  • 在类属性或方法前面添加 private 关键字,来修饰该属性或方法是私有的。
  • 私有的属性或方法只在当前类中可见,对子类和实例对象也都是不可见的!

1.4 类成员只读修饰符

除了可见性修饰符之外,还有一个常见修饰符就是: readonly(只读修饰符)
readonly
  • 表示只读用来防止在构造函数之外对属性进行赋值。
解释:
  • 使用 readonly 关键字修饰该属性是只读的,注意只能修饰属性不能修饰方法
  • 注意:属性 age 后面的类型注解(比如,此处的 number)如果不加,则 age 的类型为 18 (字面量类型)。
  • 接口或者 {} 表示的对象类型,也可以使用 readonly

2. 类型兼容性

2.1 类型兼容性

① 两种类型系统:
  • Structural Type System(结构化类型系统)
  • Nominal Type System(标明类型系统)。
TS 采用的是结构化类型系统 ,也叫做 duck typing(鸭子类型), 类型检查关注的是值所具有的形状
也就是说,在结构类型系统中,如果两个对象具有相同的形状,则认为它们属于同一类型。
解释:
  • Point 和 Point2D 是两个名称不同的类。
  • 变量 p 的类型被显示标注为 Point 类型,但是,它的值却是 Point2D 的实例,并且没有类型错误。
  • 因为 TS 是结构化类型系统,只检查 Point 和 Point2D 的结构是否相同(相同,都具有 x 和 y 两个属性,属性类型也相同)。
  • 但是,如果在 Nominal Type System 中(比如,C#、Java 等),它们是不同的类,类型无法兼容。

② 成员多的可以赋值给少的(成员少的可以兼容成员多的)

注意:
  • 在结构化类型系统中,如果两个对象具有相同的形状,则认为它们属于同一类型,这种说法并不准确。
更准确的说法:
  • 对于对象类型来说,y 的成员至少与 x 相同,则 x 兼容 y(成员多的可以赋值给少的

解释:
  • Point3D 的成员至少与 Point 相同,则 Point 兼容 Point3D。
  • 所以,成员多的 Point3D 可以赋值给成员少的 Point。

③ 除了 class 之外,TS 中的其他类型也存在相互兼容的情况,包括:

  • 接口兼容性
  • 函数兼容性 等。

2.2 接口兼容性

接口之间的兼容性,类似于 class。并且,class 和 interface 之间也可以兼容。

2.3 函数兼容性

函数之间兼容性比较复杂,需要考虑:

  • 参数个数
  • 参数类型
  • 返回值类型。

① 参数个数

参数个数 ,参数多的兼容参数少的(或者说, 参数少的可以赋值给多的
解释:
  • 参数少的可以赋值给参数多的,所以,f1 可以赋值给 f2。
  • 数组 forEach 方法的第一个参数是回调函数,该示例中类型为:(value: string, index: number, array: string[]) => void。
  • 在 JS 中省略用不到的函数参数实际上是很常见的,这样的使用方式,促成了 TS 中函数类型之间的兼容性
  • 并且因为回调函数是有类型的,所以,TS 会自动推导出参数 item、index、array 的类型。

② 参数类型

参数类型 ,相同位置的参数类型要相同(原始类型)或兼容(对象类型)。
解释:
  • 函数类型 F2 兼容函数类型 F1,因为 F1 和 F2 的第一个参数类型相同。

解释:
  • 注意,此处与前面讲到的接口兼容性冲突。
  • 技巧:
    • 将对象拆开,把每个属性看做一个个参数,则参数少的(f2)可以赋值给参数多的(f3)。
③ 返回值类型
返回值类型 ,只关注返回值类型本身即可。
解释:
  • 如果返回值类型是原始类型,此时两个类型要相同,比如,左侧类型 F5 和 F6。
  • 如果返回值类型是对象类型,此时成员多的可以赋值给成员少的,比如,右侧类型 F7 和 F8

3. 交叉类型

交叉类型&):功能类似于接口继承(extends),用于组合多个类型为一个类型常用于对象类型)。

比如:

解释:
  • 使用交叉类型后,新的类型 PersonDetail 就同时具备了 Person 和 Contact 的所有属性类型。
相当于:
交叉类型(&)和接口继承(extends)的对比:
  • 相同点:
    • 都可以实现对象类型的组合。
  • 不同点:
    • 两种方式实现类型组合时,对于同名属性之间,处理类型冲突的方式不同

说明:
  • 以上代码,接口继承会报错(类型不兼容);交叉类型没有错误,可以简单的理解为

4. 泛型

泛型 是可以在 保证类型安全 前提下,让函数等 与多种类型一起工作 ,从而 实现复用 ,常用于:
  • 函数接口class 中。
需求:
  • 创建一个 id 函数,传入什么数据就返回该数据本身(也就是说,参数和返回值类型相同)。

比如,id(10) 调用以上函数就会直接返回 10 本身。但是,该函数只接收数值类型,无法用于其他类型。
为了能让函数能够接受任意类型,可以将参数类型修改为 any。但是,这样就失去了 TS 的类型保护,类型不安全。
泛型 保证类型安全 (不丢失类型信息)的同时,可以 让函数等与多种不同的类型一起工作 ,灵活可 复用
实际上,在 C#和 Java 等编程语言中,泛型都是用来实现可复用组件功能的主要工具之一。

4.1 创建泛型函数

① 创建泛型函数:
解释:
  • 语法:
    • 在函数名称的后面添加 <>(尖括号),尖括号中添加类型变量,比如此处的 Type。
  • 类型变量 Type,是一种特殊类型的变量它处理类型而不是值。
  • 该类型变量相当于一个类型容器,能够捕获用户提供的类型(具体是什么类型由用户调用该函数时指定)。
  • 因为 Type 是类型,因此可以将其作为函数参数和返回值的类型,表示参数和返回值具有相同的类型。
  • 类型变量 Type,可以是任意合法的变量名称。
② 调用泛型函数:
解释:
  • 语法:
    • ·在函数名称的后面添加 <>(尖括号),尖括号中指定具体的类型,比如,此处的 number。
  • 当传入类型 number 后,这个类型就会被函数声明时指定的类型变量 Type 捕获到。
  • 此时,Type 的类型就是 number,所以,函数 id 参数和返回值的类型也都是 number。
同样,如果传入类型 string,函数 id 参数和返回值的类型就都是 string。
这样,通过 泛型 就做到了让 id 函数与多种不同的类型一起工作, 实现了复用的同时保证了类型安全
③ 简化调用泛型函数
解释:
  • 在调用泛型函数时,可以省略 <类型> 来简化泛型函数的调用
  • 此时,TS 内部会采用一种叫做类型参数推断的机制,来根据传入的实参自动推断出类型变量 Type 的类型。
  • 比如,传入实参 10,TS 会自动推断出变量 num 的类型 number,并作为 Type 的类型。
推荐:
  • 使用这种简化的方式调用泛型函数,使代码更短,更易于阅读。
说明:
  • 当编译器无法推断类型或者推断的类型不准确时,就需要显式地传入类型参数。

4.2 泛型约束

泛型约束
  • 默认情况下,泛型函数的类型变量 Type 可以代表多个类型,这导致无法访问任何属性。

比如,id('a') 调用函数时获取参数的长度:

解释:
  • Type 可以代表任意类型,无法保证一定存在 length 属性,比如 number 类型就没有 length。
此时,就需要为泛型 添加约束 收缩类型 (缩窄类型取值范围)。
添加泛型约束收缩类型,主要有以下两种方式:
  • 指定更加具体的类型
  • 添加约束。

① 指定更加具体的类型

比如,将类型修改为 Type[](Type 类型的数组),因为只要是数组就一定存在 length 属性,因此就可以访问了。
②  添加约束
解释:
  • 创建描述约束的接口 ILength,该接口要求提供 length 属性。
  • 通过 extends 关键字使用该接口,为泛型(类型变量)添加约束。
  • 该约束表示:传入的类型必须具有 length 属性
注意:
  • 传入的实参(比如,数组)只要有 length 属性即可,这也符合前面讲到的接口的类型兼容性。

4.3 多个泛型的类型变量约束

泛型的类型变量可以有多个,并且 类型变量之间还可以约束 (比如,第二个类型变量受第一个类型变量约束)。
比如,创建一个函数来获取对象中属性的值:
解释:
  • 添加了第二个类型变量 Key,两个类型变量之间使用(,逗号分隔。
  • keyof 关键字接收一个对象类型,生成其键名称(可能是字符串或数字)的联合类型
  • 本示例中 keyof Type 实际上获取的是 person 对象所有键的联合类型,也就是:'name' | 'age'。
  • 类型变量 Key 受 Type 约束,可以理解为:Key 只能是 Type 所有键中的任意一个,或者说只能访问对象中存在的属性。

4.4 泛型接口

泛型接口
  • 接口也可以配合泛型来使用,以增加其灵活性,增强其复用性。

解释:
  • 在接口名称的后面添加 <类型变量>,那么,这个接口就变成了泛型接口。
  • 接口的类型变量,对接口中所有其他成员可见,也就是接口中所有成员都可以使用类型变量
  • 使用泛型接口时,需要显式指定具体的类型(比如,此处的 IdFunc<nunber>)。
  • 此时,id 方法的参数和返回值类型都是 number;ids 方法的返回值类型是 number[]。
实际上,JS 中的数组在 TS 中就是一个 泛型接口
解释:
  • 当我们在使用数组时,TS 会根据数组的不同类型,来自动将类型变量设置为相应的类型。
技巧:
  • 可以通过 Ctrl + 鼠标左键(Mac:option + 鼠标左键)来查看具体的类型信息。

4.5 泛型类

泛型类
  • class 也可以配合泛型来使用。
比如,React 的 class 组件的基类 Component 就是泛型类,不同的组件有不同的 props 和 state。
解释:
  • React.Component 泛型类两个类型变量,分别指定 props 和 state 类型。
① 创建泛型类:
解释:
  • 类似于泛型接口,在 class 名称后面添加 <类型变量>,这个类就变成了泛型类。
  • 此处的 add 方法,采用的是箭头函数形式的类型书写方式。
类似于泛型接口,在创建 class 实例时,在类名后面通过 <类型> 来指定明确的类型。

4.6 泛型工具类型

泛型工具类型
  • TS 内置了一些常用的工具类型,来简化 TS 中的一些常见操作。
说明:
  • 它们都是基于泛型实现的(泛型适用于多种类型,更加通用),并且是内置的,可以直接在代码中使用。
这些工具类型有很多,主要学习以下几个:
  • Partial<Type>
  • Readonly<Type>
  • Pick<Type, Keys>
  • Record<Keys, Type>

① 泛型工具类型 - Partial<Type>

泛型工具类型 - Partial<Type> 用来构造(创建)一个类型,将 Type 的所有属性设置为可选

解释:
  • 构造出来的新类型 PartialProps 结构和 Props 相同,但所有属性都变为可选的。

② 泛型工具类型 - Readonly<Type>

泛型工具类型 - Readonly<Type> 用来构造一个类型,将 Type 的所有属性都设置为 readonly(只读)
解释:
  • 构造出来的新类型 ReadonlyProps 结构和 Props 相同,但所有属性都变为只读的。

当我们想重新给 id 属性赋值时,就会报错:无法分配到 "id" ,因为它是只读属性。

③ 泛型工具类型 - Pick<Type, Keys>

泛型工具类型 - Pick<Type, Keys> 从 Type 中选择一组属性来构造新类型
解释:
  • Pick 工具类型有两个类型变量:
    • 表示选择谁的属性
    • 表示选择哪几个属性。
  • 其中第二个类型变量,如果只选择一个则只传入该属性名即可。
  • 第二个类型变量传入的属性只能是第一个类型变量中存在的属性
  • 构造出来的新类型 PickProps,只有 id 和 title 两个属性类型。

④ 泛型工具类型 - Record<Keys,Type>

泛型工具类型 - Record<Keys,Type> 构造一个对象类型,属性键为 Keys,属性类型为 Type

解释:
  • Record 工具类型有两个类型变量:
    • 表示对象有哪些属性
    • 表示对象属性的类型
  • 构建的新对象类型 RecordObj 表示:
    • 这个对象有三个属性分别为a/b/c,属性值的类型都是 string[]。

5. 索引签名类型

绝大多数情况下,我们都可以在使用对象前就确定对象的结构,并为对象添加准确的类型。
使用场景:
  • 当无法确定对象中有哪些属性(或者说对象中可以出现任意多个属性),此时,就用到索引签名类型了

解释:
  • 使用 [key: string] 来约束该接口中允许出现的属性名称。表示只要是 string 类型的属性名称,都可以出现在对象中。
  • 这样,对象 obj 中就可以出现任意多个属性(比如,a、b 等)。
  • key 只是一个占位符,可以换成任意合法的变量名称。
  • 隐藏的前置知识:
    • JS 中对象({})的键是 string 类型的
在 JS 中数组是一类特殊的对象,特殊在 数组的键(索引)是数值类型 。并且,数组也可以出现任意多个元素。所以,在数组对应的泛型接口中,也用到了索引签名类型。
解释:
  • MyArray 接口模拟原生的数组接口,并使用 [n: number] 来作为索引签名类型。
  • 该索引签名类型表示:
    • 只要是 number 类型的键(索引)都可以出现在数组中,或者说数组中可以有任意多个元素。
  • 同时也符合数组索引是 number 类型这一前提。

6. 映射类型

映射类型

  • 基于旧类型创建新类型(对象类型),减少重复、提升开发效率。
比如,类型 PropKeys 有 x/y/z,另一个类型 Type1 中也有 x/y/z,并且 Type1 中 x/y/z 的类型相同:
这样书写没错,但 x/y/z 重复书写了两次。像这种情况,就可以使用映射类型来进行简化。
解释:
  • 映射类型是基于索引签名类型的,所以,该语法类似于索引签名类型,也使用了 []
  • Key in PropKeys 表示 Key 可以是 PropKeys 联合类型中的任意一个,类似于 forin(let k in obj)。
  • 使用映射类型创建的新对象类型 Type2 和类型 Type1 结构完全相同。
  • 注意:
    • 映射类型只能在类型别名中使用不能在接口中使用
映射类型 除了根据联合类型创建新类型外,还可以根据对象类型来创建:
解释:
  • 首先,先执行 keyof Props 获取到对象类型 Props 中所有键的联合类型即,'a' | 'b' | 'c'。
  • 然后,Key in ... 就表示 Key 可以是 Props 中所有的键名称中的任意一个。

实际上,前面讲到的 泛型工具类型 (比如,Partial<Type>)都 是基于映射类型实现的
比如,Partial<Type> 的实现:
解释:
  • keyof T 即 keyof Props 表示获取 Props 的所有键,也就是:'a' | 'b' | 'c'。
  • 在 [] 后面添加 ?(问号),表示将这些属性变为可选的,以此来实现 Partial 的功能。
  • 冒号后面的 T[P] 表示获取 T 中每个键对应的类型。比如,如果是 'a' 则类型是 number;如果是 'b' 则类型是 string。
  • 最终,新类型 PartialProps 和旧类型 Props 结构完全相同,只是让所有类型都变为可选了。

刚刚用到的 T[P] 语法,在 TS 中叫做索引查询(访问)类型

作用:用来查询属性的类型。

解释:
  • Props['a'] 表示查询类型 Props 中属性 'a' 对应的类型 number。所以,TypeA 的类型为 number。
注意:
  • [] 中的属性必须存在于被查询类型中,否则就会报错。

索引查询类型的其他使用方式:同时查询多个索引的类型

解释:
  • 使用字符串字面量的联合类型,获取属性 a 和 b 对应的类型,结果为: string | number。

解释:
  • 使用 keyof 操作符获取 Props 中所有键对应的类型,结果为: string | number | boolean。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2055762.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【深度学习入门项目】基于支持向量机的手写数字识别

目录 导入必要的包1. 数据集2. 数据处理3. 训练过程4. 输出结果完整代码 本项目使用SVM训练模型&#xff0c;用于预测手写数字图片。 导入必要的包 numpy: 这个库是Python中常用的数学计算库。在这个项目中&#xff0c;我使用numpy来处理图像数据&#xff0c;将图像数据转换为…

FPGA开发——DS18B20读取温度并且在数码管上显示

一、简介 在上一篇文章中我们对于DS18B20的相关理论进行了详细的解释&#xff0c;同时也对怎样使用DS18B20进行了一个简单的叙述。在这篇文章我们通过工程来实现DS18B20的温度读取并且实现在数码管伤显示。 1、基本实现思路 根据不同时刻的操作&#xff0c;我们可以使用一个状…

基于vue框架的班级网站的设计与实现vg66m(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;班级,学生,班级活动,班级相册,班级开支,活动记录 开题报告内容 基于Vue框架的班级网站设计与实现 开题报告 一、引言 随着互联网技术的飞速发展&#xff0c;网络已经成为人们日常生活中不可或缺的一部分。在教育领域&#xff0c;班级…

大白话解析:深入浅出大模型RAG模块全解析

文章目录 什么是 RAG&#xff1f; 技术交流&资料通俗易懂讲解大模型系列 RAG模块化 什么是模块化RAG&#xff1f; 索引模块 块优化 滑动窗口从小到大元数据附加 结构化组织 层次化索引知识图谱文档组织 预检索模块 查询扩展 多查询子查询CoVe 查询转换 重写HyDE 查询路由…

TON链上游戏项目开发基本要求及模式创建与海外宣发策略

TON&#xff08;The Open Network&#xff09;是由Telegram开发的区块链平台&#xff0c;以其高速、低延迟、和高扩展性吸引了大量开发者和项目方。TON链上游戏项目作为一个新兴领域&#xff0c;结合了区块链技术和游戏产业&#xff0c;为用户提供了全新的游戏体验和经济激励。…

精益生产咨询:为企业量身定制的高效能蜕变计划!——张驰咨询

在当今这个快速变化、竞争激烈的市场环境中&#xff0c;企业如何保持持续的竞争优势&#xff0c;提高生产效率&#xff0c;降低成本&#xff0c;同时又能快速响应市场需求&#xff0c;成为了每一个企业家必须面对的重大课题。精益生产&#xff08;Lean Production&#xff09;作…

第5节:Elasticsearch核心概念

我的后端学习笔记大纲 我的ElasticSearch学习大纲 1.Lucene和Elasticsearch的关系: 1.Lucene&#xff1a;最先进、功能最强大的搜索库&#xff0c;直接基于lucene开发&#xff0c;非常复杂&#xff0c;api复杂2.Elasticsearch&#xff1a;基于lucene&#xff0c;封装了许多luc…

跳槽?面试软件测试需要掌握的知识你Get了吗

想从事软件测试相关的工作&#xff0c;立志成为一名优秀的软件测试工程师。 一名优秀的软件测试工程师&#xff0c;需要扎实的专业基础&#xff0c;包括测试相关技术、编程技能、数据库知识、计算机网络、以及操作系统等等。对于没有测试经验的应届生求职者来说&#xff0c;面…

SpringBoot项目部署时application.yml文件的加载优先级和启动脚本

文章目录 application.yml文件的加载优先级(由高到低)第一级命令行参数第二级Jar包同级目录 /config第三级Jar包同级目录第四级classpath 下的/config第五级classpath 根路径/总结&#xff1a; logback.xml 文件加载顺序当application.yml 和 bootstrap.yml 同时存在时java jar…

淘宝天猫详情接口API:实现轻松购物,探索最具性价比的商品

随着电子商务的蓬勃发展&#xff0c;网络购物已经成为现代人日常生活中的重要部分。在这个浩瀚的电商海洋中&#xff0c;淘宝和天猫无疑是最为耀眼的两大平台。然而&#xff0c;如何在众多的商品中挑选出性价比最高的产品&#xff1f;淘宝天猫详情接口API为您提供了解决方案。 …

基于vue框架的班级管理系统3pdep(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;学生,班级事务,班级,成绩信息,请假,销假,班级信息,教师 开题报告内容 基于Vue框架的班级管理系统 开题报告 一、引言 随着教育信息化进程的加快&#xff0c;学校管理工作逐渐从传统的纸质化、人工化向数字化、智能化转变。班级作为学…

Python与自动化测试:提高软件质量和稳定性

在软件开发过程中&#xff0c;自动化测试是提高软件质量和稳定性的重要手段之一。Python作为一种简洁而强大的编程语言&#xff0c;为自动化测试提供了丰富的工具和库。本文将介绍几个常见的自动化测试案例&#xff0c;并提供详细的Python代码示例&#xff0c;帮助您更好地理解…

前端面试——js作用域

说一说JS的作用域吧 作用域的分类 作用域分为&#xff1a;全局作用域&#xff0c;函数作用域&#xff0c;块级作用域 作用域的特性 全局作用域&#xff1a; 能够让变量和函数在全局位置访问&#xff0c;其挂载在浏览器的window对象下面 其中var定义的变量和function函数存…

怀旧风吹到体育圈,刘翔、郭晶晶等再翻红?明星与体育冠军代言的区别!

今年奥运&#xff0c;怀旧风吹到了体育圈&#xff0c;曾经的奥运冠军如刘翔、郭晶晶等再度成为公众焦点。这段时间&#xff0c;刘翔频频出现在伊利、霸王茶姬等品牌的广告中&#xff0c;还和法国球星姆巴佩合作拍摄了小红书广告。同样备受品牌关注的还有郭晶晶&#xff0c;巴黎…

【Python实现全屏播放视频】

效果如下&#xff1a; 虽然视频比较抽象&#xff0c;但是确实是用python(cv2)实现的 代码&#xff1a; import cv2 from playsound import playsound from threading import Threaddef func1():cap cv2.VideoCapture("mp4/out.mp4") #替换为视频路径ret, frame ca…

记一次长事务方法带来的坑

文章目录 1. 沟通需求2.分析需求3. 波折起4.初版完成5.锁等待超时6.消费者超时7.总结 1. 沟通需求 产品找到我说&#xff0c;咱要将一波数据给更新了&#xff0c;因为涉及业务&#xff0c;就不说具体的内容了&#xff0c;需要支持分页滚动&#xff0c;校对数据后进行推送&…

无人机系统的关键技术

一、飞控系统&#xff1a;是无人机完成整个飞行过程的关键&#xff0c;决定了无人机的飞行性能和稳定性。 二、导航系统&#xff1a;提供无人机所需的位置、速度和飞行姿态等信息&#xff0c;引导无人机按照指定航线飞行。 三、动力系统&#xff1a;提供飞行动力&#xff0c;…

报表工具是开源还是商用的好?如何选择适合自己的报表工具?

在当今数字化转型的浪潮中&#xff0c;制作既精确又直观的报表已成为个人高效工作与企业精准沟通的核心工具。然而&#xff0c;面对市场上纷繁复杂的报表工具选项&#xff0c;选择最适合自身或企业需求的那一款&#xff0c;宛如漫步于迷雾笼罩的森林&#xff0c;挑战重重&#…

React 学习——useMemo

useMemo使用场景&#xff1a;消耗非常大的计算&#xff0c;例如递归 import { useMemo, useState } from react; // 缓存&#xff1a;消耗非常大的计算&#xff0c;例如递归 function fib(n){console.log(fib);if(n < 3)return 1;return fib(n-2) fib(n-1); }const App (…

Python开发工具PyCharm v2024.2全新发布——新增Databricks集成

JetBrains PyCharm是一种Python IDE&#xff0c;其带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具。此外&#xff0c;该IDE提供了一些高级功能&#xff0c;以用于Django框架下的专业Web开发。 立即获取PyCharm v2024.2正式版(Q技术交流&#xff1a;786598704&…