【TypeScript】TS入门到实战(详解:高级类型)

目录

第三章、TypeScript的数据类型

3.1 TypeScript的高级类型

3.1.1 class

3.1.1.1 熟悉class类

3.1.1.2 class类继承的两种方式

3.1.1.3 class类的5种修饰符

3.1.2 类型兼容

3.1.3 交叉类型

3.1.4 泛型

3.1.4.1 创建泛型函数

3.1.4.2 泛型函数的调用

3.1.4.3 泛型约束

3.1.4.4 泛型接口

3.1.4.5 泛型类

3.1.4.6 泛型工具类型

3.1.5 索引签名类型

3.1.6  映射类型


第三章、TypeScript的数据类型

3.1 TypeScript的高级类型

3.1.1 class

3.1.1.1 熟悉class类
  • 引言
class Person {}
const p = new Person()

当创建一个Person类时,添加了实例对象p,由类型推论可以知道它的类型是Person;说明TS 中的 class,不仅提供了 class 的语法功能,也作为一种类型存在。接下来跟着小编一起理解class吧。

  • 初始化属性
class Person {age: number // 适用没有默认值name = 'VE' // 适用于有默认值
}
  1. 声明成员 age,类型为 number(没有初始值)。
  2. 声明成员 name,并设置初始值,此时,可省略类型注解(TS 类型推论 为 string 类型)。
  3. 当没有默认赋值时,需要自定义属性的类型,否则会默认为any类型赋值后,属性的类型会与赋值的类型一致,赋值的类型ts会类型推论
  4. 看下图的几种情况:

 

  • 构造函数
class Person {age: numbername: stringconstructor (name: string, age: number){ // 初始化实例对象使用的,写了contructor函数后初始化实例对象时也需要传参从而初始化实例中的属性this.age = agethis.name = name}
}
const p = new Person('10', 10)
  1. 只有初始化(比如,age: number)后,才可以通过 this.age 来访问实例成员。
  2. 需要为构造函数指定类型注解,否则会被隐式推断为 any;构造函数不需要返回值类型。
  3. constructor构造函数是初始化实例对象使用的,写了contructor函数后初始化实例对象时也需要通过传参从而初始化实例中的属性参数顺序跟constructor一致

 

  • 实例方法
class Point {x: numbery: numberscale (n: number): void{this.x *= nthis.y *= n}
}
  1. 方法初始化,它的的类型注解(参数和返回值)与函数用法相同

3.1.1.2 class类继承的两种方式

类继承的两种方式:1、extends(继承父类) 2、implements(实现接口)
注意:JS 中只有 extends,而 implements 是 TS 提供的。

  • extends(继承父类)
class Animal { // 这是父类Animal distance: string = '10' // 父类中的属性move () { // 父类中的方法console.log('move along')}
}class Dog extends Animal { // 子类 Dog 继承父类 Animabark () { // 子类自身的方法console.log('汪汪汪~')}
}const dog = new Dog() // dog是Dog的实例对象,// 从而dog同时具有了父类 Animal 和 子类 Dog 的所有属性和方法
dog.move()
dog.bark()
dog.distance = '20'
console.log('距离', dog.distance)

  1. 通过 extends 关键字实现继承。
  2. 子类 Dog 继承父类 Animal,则 Dog 的实例对象 dog 就同时具有了父类 Animal 和 子类 Dog 的所有属性和方法。
  • implements(实现接口): 这是ts新增的,顾名思义就是对一个接口的实现

interface Singable { // 这是添加的一个接口,定义了Singable有哪些属性和方法的类型name: string sing: () => voidtoSing(): void
}class Person implements Singable { // Person类是对Singable接口的实现name = 'VE'sing = () => { // 函数方面是箭头函数还是普通函数需要我们自己规范console.log('你是我的小啊小苹果')}toSing(): void {console.log('去ktv唱歌')}
}const p = new Person() // p是Person的一个实例对象// 从而拥有了Singable 接口 指定的所有方法和属性
console.log(p.name)
p.sing()
p.toSing()

  1. 通过 implements 关键字让 class 实现接口。
  2. Person 类实现接口 Singable 意味着,Person 类中必须提供 Singable 接口中指定的所有方法和属性。
3.1.1.3 class类的5种修饰符

可见性修饰符包括:1、public(公有的) 2、protected(受保护的) 3、private(私有的)4、readonly(只读修饰符)5、static(静态的)

  • public(公有的)

class Animal {public move () { // 在父类的方法中添加pubilc(默认,可省略)console.log('move along')}
}
class Dog extends Animal { // 子类bark () {console.log('汪汪汪~')}
}class Cat extends Animal { // 子类bark () {console.log('喵~喵~喵~')}
}const dog = new Dog() // 由于父类设置的为pubilc修饰符,所有其子类实例可以调用父类的方法dog.move()
dog.bark()const cat = new Cat() // 由于父类设置的为pubilc修饰符,所有其子类实例可以调用父类的方法cat.move()
cat.bark()

  1. 在类属性或方法前面添加 public 关键字,来修饰该属性或方法是共有的
  2.  因为 public 是默认可见性,所以,可以直接省略
  • protected(受保护的)

class Animal {protected move () { // 将方法添加protected关键字设置成受保护的,console.log('move along')}toMove () {this.move() // 在父类本身中只能通过this访问受保护的属性/方法}
}
class Dog extends Animal {bark () {console.log('汪汪汪~')this.move() // 在子类中也只能通过this访问受保护的属性/方法}
}
// const animal = new Animal() // 但是他们的实例不能访问到受保护的属性和方法
// animal.move() // 本身实例调用会报错属性move受保护,只能在类“Animal”及其子类中访问const dog = new Dog()// dog.move() // 子类调用会报错属性move受保护,只能在类“Animal”及其子类中访问
dog.bark() // 可以通过提供方法添加新的方法从而间接访问
console.log('=====')
dog.toMove()

  1. 在类属性或方法前面添加 protected 关键字,来修饰该属性或方法是受保护的
  2. 在子类的方法内部可以通过 this 来访问父类中受保护的成员,但是,对其声明所在类和子类不可见!
  • private(私有的)

class Animal {private move () {console.log('move along') // 将方法添加private 关键字设置成私有的,}toMove () {this.move() // 只能在当前类中访问}
}
class Dog extends Animal {bark () {console.log('汪汪汪~')// this.move() // 在子类的方法中也不能访问}
}
// const animal = new Animal()
// animal.move() // 本身实例调用会报错属性move斯私有属性,只能在类“Animal”中访问const dog = new Dog()// dog.move() // 子类调用会报错属性move为私用属性,只能在类“Animal”中访问
dog.bark()
console.log('=====')
dog.toMove()  // 但是子类可以通过调用父类提供的方法从而间接的访问父类的私有属性

 

  1. 在类属性或方法前面添加 private 关键字,来修饰该属性或方法是私有的
  2.  私有的属性或方法只在当前类中可见,对子类和实例对象也都是不可见的!
  • readonly(只读修饰符)

class Animal {readonly species: string = '爬行动物' // 修饰属性为只读是, 仅可在构造函数中修改move () {// this.species = '飞行动物' // 报错无法赋值,species为只读属性console.log('move along')}constructor(species: string){this.species = species}
}
class Dog extends Animal {bark () {console.log('汪汪汪~')}
}const dog = new Dog('爬行')dog.bark()
console.log('dog', dog.species)

 

  1. 使用 readonly 关键字修饰该属性是只读的,注意只能修饰属性不能修饰方法。
  2. 注意:只要是readonly来修是属性,必须手动提供明确的类型,属性 species 后面的类型注解(比如,此处的 string)如果不加,则 species 的类型为 爬行动物 (字面量类型)。
  3. 仅可在构造函数中修改(也就是初始化时)
  4. 接口或者 {} 表示的对象类型,也可以使用 readonly
// 接口或者 {} 表示的对象类型,也可以使用 readonly
interface IPerson {readonly name: string
}let p: IPerson = {name: 'VE'
}let per: { readonly name: string, age: number } = {name: 'VE',age: 18
}// p.name = 'LO' // 如果没加readonly是可以修改的,但是加了之后会报错为只读属性,无法赋值
// per.name = 'LO'
per.age = 20
  • static(静态的)
class Animal {// 普通属性name: string// 静态属性static gander: string = '女'// 构造函数前不能添加 staticconstructor (name: string) {this.name = name// 访问静态属性,需要通过 【类名.属性】访问console.log(this.name, Animal.gander)}// 普通方法sayHi () {console.log('hello你们好')}// 静态方法static sayStatic () {console.log(Animal.gander)}
}
// 实例化对象
const per = new Animal('花花')
// 访问普通方法,通过实例
per.sayHi()
// 访问静态方法,要通过 【类名.方法】访问
Animal.sayStatic()
  1. 使用 static 关键字修饰该属性/方法是静态的
  2. 静态成员 在使用时通过 类名.静态成员 这种语法来调用的,而不是通过 this实例

3.1.2 类型兼容

  • 目前有两种类型系统:1 Structural Type System(结构化类型系统) 2 Nominal Type System(标明类型系统)
  • TS 采用的是结构化类型系统,也叫做 duck typing(鸭子类型),类型检查关注的是值所具有的形状。也就是说,在结构类型系统中,如果两个对象具有相同的形状,则认为它们属于同一类型。(可以这么理解但是,该说法并不准确)。用于确定一个类型是否能赋值给其他类型
  • 对于对象类型来说,y 的成员至少与 x 相同,则 x 兼容 y(成员多的可以赋值给少的)
  • 例子1:
class Point {number1 = 10; number2 = 9}
class Point2D {number1 = 16; number2 = 12}const p: Point = new Point2D()
console.log('p', p.number1, p.number2)

  1. Point 和 Point2D 是两个名称不同的类。
  2. 变量 p 的类型被显示标注为 Point 类型,但是,它的值却是 Point2D 的实例,并且没有类型错误。
  3. 因为 TS 是结构化类型系统,只检查 Point 和 Point2D 的结构是否相同(结果是相同,都具有 x 和 y 两个属性,属性类型也相同)。
  4. 但是,如果在 Nominal Type System(标明类型系统) 中(比如,C#、Java 等),它们是不同的类,类型无法兼容。
  5. 这里我们可以理解p被类型标注了Point的number1与number2,分别都是number类型,最后被赋值了Point2D
  • 例子2:兼容可以立即成向下兼容,在class中定义:成员多的可以赋值给成员少的(理解,左边的参数必须都有,而右边赋值的则是至少需要包含左边参数)
class Point {number1 = 10; number2 = 9}
class Point2D {number1 = 16; number2 = 12}
class Point3D {number1 = 17; number2= 1; numbe3 = 20 }
const p: Point = new Point2D()
const p1: Point2D = new Point3D() // 成员多的 Point3D 可以赋值给成员少的Point2D / Point
console.log('p', p.number1, p.number2)

…… 

3.1.3 交叉类型

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

interface Person { // 第一个接口定义了一部分类型name: string
}
interface Contact { // 第二个接口定义了不部分类型phone: string
}type PersonDetail = Person & Contact // 定义新的类型利用&交叉类型合并, 注hengsm意新的类型用tpye类型别名声明的let person: PersonDetail = { // 新的类型同时拥有上面的两种声明类型name: 'zs',phone: '177 5490 0987'
}
  1. 使用交叉类型后,新的类型 PersonDetail 就同时具备了 Person 和 Contact 的所有属性类型。
  2.     相当于type PersonDetail = { name: string, phone: string }
  • 交叉类型(&)和接口继承(extends)的对比

-- 使用extends

interface A {name: stringfn: (number: number) => void
}
interface B extends A {gander: string//  fn: (number: string) => void
}
const obj: B = {name: 'VE',fn: (number: number) => {},gander: '女'
}

-- 使用交叉类型

interface A {name: stringfn: (number: number) => number
}
interface B {// name: numberfn: (number: string) => string
}
type C = B & A
const obj: C = {// name,name: '',fn: (number) => {return number}
}

-- 相同点:都可以实现对象类型的组合。
-- 不同点:两种方式实现类型组合时,对于同名属性之间,处理类型冲突的方式不同
       extends 不支持相同属性/方法的继承,会报错类型不兼容
       & 支持相同属性/方法的继承可以理解成利用联合类型 & 连接,两种类型同时具备才可,否则会报错,不可分配

3.1.4 泛型

  • 泛型是可以在保证类型安全前提下,让函数等与多种类型一起工作,从而实现复用,常用于:函数、接口、class 中。

3.1.4.1 创建泛型函数
  • 引入思考:目前有一个需求,创建一个 id 函数,传入什么数据就返回该数据本身(也就是说,参数和返回值类型相同)

// 实现方法一:手动限制一个类型,缺点也很明显,我们只能传number数据类型,传其他数据类型时会报错
function id_first(value: number) {return value
}
// 实现方法二:不限制数据类型,那么ts本身类型推断,则会将传参推断为any,失去了ts的意义
function id_second(value) {return value
}
  •  实现方法:创建泛型函数,泛型在保证类型安全(不丢失类型信息)的同时,可以让函数等与多种不同的类型一起工作,灵活可复用。
// 实现方法:创建泛型函数,泛型在保证类型安全(不丢失类型信息)的同时,可以让函数等与多种不同的类型一起工作,灵活可复用。
function id<Type>(value: Type): Type {return value
}
  1.  语法:在函数名称的后面添加 <>(尖括号)尖括号中添加类型变量(可自定义语义化名称),比如此处的 Type。
  2. 该函数中类型变量 Type,是一种特殊类型的变量,它处理类型而不是值。
  3.  该类型变量相当于一个类型容器,能够捕获用户提供的类型(具体是什么类型由用户调用该函数时指定)。
  4.  因为 Type 是类型,因此可以将其作为函数参数和返回值的类型,表示参数和返回值具有相同的类型。
  5. 类型变量 Type,可以是任意合法的变量名称
3.1.4.2 泛型函数的调用
  • 正常调用 
function id<Type>(value: Type): Type {return value
}// 调用泛型函数:既要传类型,也要传参数
const num = id<number>(1)
const str = id<string>('10')
const arr = id<(number | string)[]>(['10', '1', 10])

  1. 语法:在函数名称的后面添加 <>(尖括号),尖括号中指定传参的具体的类型,比如,此处的 number。
  2. 当传入类型 number 后,这个类型就会被函数声明时指定的类型变量 Type 捕获到。
  3.  此时,Type 的类型就是 number,所以,函数 id 参数和返回值的类型也都是 number
  • 简化调用
function id<Type>(value: Type): Type {return value
}// <类型> 可以不写
let sp_num = id(10)
let sp_str = id('10')
let sp_arr = id(['10', '1', 10])

主要注意:这种方法是利用类型推断实现的,直接传参要与前面带类型的要区分 

  1. 例如sp_num、sp_str变量,我们能发现函数被推断成id<10>(value: 10): 10 字面量类型,最终返回数字10才使得sp_num推断成number类型
  2. 例如sp_arr变量,函数被推断<(string | number)[]>(value: (string | number)[]): (string | number)[],最终返回结果['10', '1', 10]使得sp_arr推断成(string | number)[]类型
  3.  如果我们期望第1点最终是number类型而不是字面量类型,但是类型推断又是给我们推断成字面量类型,我们还是需要传类型的:id<number>(10)
3.1.4.3 泛型约束
  • 默认情况下泛型函数的类型变量 Type 可以代表多个类型,这导致无法访问任何属性,如下:

function id_view<Type>(value: Type): Type {console.log('长度', value.length) // 报错原因:Type 可以代表任意类型,无法保证一定存在 length 属性,比如 number 类型没有 length。return value
}

  • 于是,就需要为泛型添加约束来收缩类型(缩窄类型取值范围),添加泛型约束收缩类型,主要有以下两种方式:1、指定更加具体的类型 2、添加约束

  • 1、指定更加具体的类型

例如:将类型修改为 Type[](Type 类型的数组),因为只要是数组就一定存在 length 属性,因此就可以访问了

function id_view<Type>(value: Type[]): Type[] { // 将类型修改为 Type[](Type 类型的数组),因为只要是数组就一定存在 length 属性,因此就可以访问了console.log('长度', value.length)return value
}id_view([1, 2])
id_view<number | string>([1, '2'])
id_view<number[]>([1, 2]) // 注意添加<类型>是的写法,由于我们已经在类型中写了Type[],所以使用时不需要再加[]

注意书写:(类型可不传,ts会通过类型断言得到)

 报错:

  • 2、添加约束 
interface ILength { length: number } // 创建描述约束的接口 ILength,提供length属性function id_view<Type extends ILength>(value: Type): Type { // 对Type添加约束,通过 extends 关键字使用ILength接口console.log('长度', value.length)return value
}// 使用类型约束之后我们在调用时就必须需要传具有 length 属性的类型(string/array…),否则调用会报错
// id_view<number>(10) // 会报错number类型不满足约束的ILength
id_view('10')
id_view<string>('10')
// id_view<{name: string, age: number}>({name: 'VE', age: 23}) // 会报错
  1. 创建描述约束的接口 ILength,该接口要求提供 length 属性
  2. 通过 extends 关键字使用该接口,为泛型(类型变量)添加约束。
  3. 该约束表示:传入的类型必须具有 length 属性
  • 泛型的类型变量可以有多个,并且类型变量之间还可以约束

function getProp<Type, Key extends keyof Type>(obj: Type, key: Key) { // keyof 关键字接收一个对象类型,生成其键名称(可能是字符串或数字)的联合类型return obj[key]
}
let person = {name: 'VE', age: 23}
const personName = getProp(person , 'name')
console.log('personName', personName)
  1. 添加了第二个类型变量 Key,两个类型变量之间使用(,)逗号分隔。
  2.  keyof 关键字接收一个对象类型,生成其键名称(可能是字符串或数字)的联合类型
  3. 本示例中 keyof Type 实际上获取的是 person 对象所有键的联合类型,也就是:'name' | 'age'。
  4. 类型变量 Key 受 Type 约束,可以理解为:Key 只能是 Type 所有键中的任意一个,或者说只能访问对象中存在的属性

3.1.4.4 泛型接口
  • 接口配合泛型使用,以增加其灵活性,复用性

interface idFunc<Type> {id: (vlue: Type) => Typeids: () => Type[]
}
const obj: idFunc<number> = { // 使用泛型接口时,必须需要显式指定具体的类型id(num) {return num},ids() {return [1, 2]}
}
  1. 语法:在接口名称的后面添加 <类型变量>,那么,这个接口就变成了泛型接口。
  2. 接口的类型变量,对接口中所有其他成员可见,也就是接口中所有成员都可以使用类型变量
  3. 使用泛型接口时,需要显式指定具体的类型(比如,此处的 IdFunc<number>)。
  4. 此时,id 方法的参数和返回值类型都是 number;ids 方法的返回值类型是 number[]。
  • JS 中的数组在 TS 中就是一个泛型接口:当我们在使用数组的方法时,TS 会根据数组的不同类型,来自动将类型变量设置为相应的类型,如下:

const strsArr = ['a', 'b', 'c']
const arr1 = [1, 2, 'a']
strsArr.sort()
arr1.sort()
arr1.forEach(()=>{})

 

3.1.4.5 泛型类
  • 使用class类 配合泛型来使用

  • 创建泛型类并使用

关于创造泛型类涉及到的报错:

【TypeScript 类报错】Property ‘name‘ has no initializer and is not definitely assigned in the constructor-CSDN博客

class GenericNumber<NumType> { // 创建泛型类defaultValue: NumTypeadd?: ( x: NumType, y: NumType ) => NumTypeconstructor(defaultValue: NumType) { // 创建构造函数this.defaultValue = defaultValue}
}
const myNum = new GenericNumber<number>(10) // 类似于泛型接口,在创建 class 实例时,在类名后面通过 <类型> 来指定明确的类型。
myNum.defaultValue = 10
// 初始化方法
myNum.add = function(a, b) {return a + b
}
// 之后调用方法
const value = myNum.add(1, 2)
console.log(myNum.defaultValue, value)

(针对于泛型类里的方法创造了实例之后一定要先初始化再调用)

3.1.4.6 泛型工具类型
  • TS 内置了一些常用的工具类型,来简化 TS 中的一些常见操作,它们都是基于泛型实现的(泛型适用于多种类型,更加通用),并且是内置的,可以直接在代码中使用。

  • 常用的:1、Partial<Type>  2、 Readonly<Type> 3、 Pick<Type, Keys> 4 、Record<Keys, Type>

  • 1、Partial<Type>:用来构造(创建)一个类型,将 Type 的所有属性设置为可选
interface Props {id: stringchildren: number[]
}// 构造出来的新类型 PartialProps 结构和 Props 相同,但所有属性都变为可选的。鼠标悬浮在PartialProps上可以发现PartialProps的属性都添加了?:表示可有可无
type PartialProps = Partial<Props> 
let partialVal: PartialProps = {} // 添加Partial后,参数可写可不写
let noPartialVal: Props = { // 未添加Partial,使用该类型字段必须都传id: '1',children: [1, 2]
}

  • 2、Readonly<Type> 用来构造一个类型,将 Type 的所有属性都设置为 readonly(只读)
interface Props {id: stringchildren: number[]
}type readonlyProps = Readonly<Props> // 会给每一个类型前面添加一个 readonly 修饰
let readonVal: readonlyProps = { // 一旦定义里面的属性就无法修改id: '001',children: [1, 2, 3]
}
// readonVal.id = '002' // 无法修改,报错无法赋值,为只读属性

  • 3、Pick<Type, Keys> 从 Type 中选择一组已有的属性来构造新类型
interface Props {id: stringchildren: number[]
}type PickProps = Pick<Props, 'id'>
let PickVal: PickProps = {id: '',
}
// 如果传多个使用 | 连接,选择的不能是类型中没有的属性
type PickProps = Pick<Props, 'id' | 'children'> 
let PickVal: PickProps = {id: '',children: [1, 2, 3]
}
  • 4、Record<Keys,Type> 构造一个对象类型,属性键为 Keys ,使用 | 连接多个属性,属性类型为 Type。
interface Props {id: stringchildren: number[]
}type RecordProps = Record<'id', Props>
let RecordVal: RecordProps = {id: {id: '',children: [1, 2]}
}
type RecordProps2 = Record<'id' | 'title', string>
let RecordVal2: RecordProps2 = {id: '',title: ''
}

3.1.5 索引签名类型

  • 绝大多数情况下,我们都可以在使用对象前就确定对象的结构,并为对象添加准确的类型。
  • 使用场景:当无法确定对象中有哪些属性(或者说对象中可以出现任意多个属性),此时,就用到索引签名类型了
interface AnyObject {[key: string]: number
}
let obj: AnyObject = {a: 1,b: 22,1: 2
}

  1. 使用 [key: string] 来约束该接口中允许出现的属性名称。表示只要是 string 类型的属性名称,都可以出现在对象中
  2.  这样,对象 obj 中就可以出现任意多个属性(比如,a、b 等)。
  3. key 只是一个占位符,可以换成任意合法的变量名称。
  4. 隐藏的前置知识:JS 中对象({})的键是 string 类型的。
interface MyArray<T> {[key: number]: T // 索引都是数字,数组符合要求,T规定类型
}
let arr: MyArray<number> = [1, 2, 3]
  1. 在 JS 中数组是一类特殊的对象,特殊在数组的键(索引)是数值类型。
  2. 并且,数组也可以出现任意多个元素。所以,在数组对应的泛型接口中,也用到了索引签名类型

3.1.6  映射类型

小编重开一篇文章单独讲。

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

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

相关文章

Chirp信号生成(FPGA、基于cordic IP核)

一、Chirp生成模块介绍 采用Verilog 生成Chirp&#xff0c;实现输入使能电平&#xff0c;模块输出Chirp信号&#xff0c;Chirp信号频率范围&#xff0c;时间宽度&#xff0c;连续Chirp信号数量可配置。 二、模块例化方法示例 parameter FL d20_000 ; parameter FH…

linux命令行操作

一、看二进制文件 od -t x1 1.txt | less 二、看信号 kill -l man 7 signal 三、查看当前进程的pid号 echo $$

Python绘制动态股价曲线图并保存视频

用akshare库获取英伟达(股票代码&#xff1a;105.NVDA) 在2014年6月19日到2024年6月19日期间的股票的收盘价数据&#xff08;用后复权的收盘价&#xff09;&#xff1b; 基于后复权的收盘价数据&#xff0c;做一个动态股价曲线图&#xff0c;逐日显示英伟达股价的动态变化情况&…

PHP反序列化字符逃逸详解

这段时间遇到几个关于反序列化的字符逃逸的程序&#xff0c;今天来分享一下经验。 <?php function filter($str){ return str_replace(bb, ccc, $str); } class A{ public $nameaaaa; public $pass123456; } $AAnew A(); $resfilter(serialize($AA)); $cunserialize($res)…

Vue报错:Component name “xxx” should always be multi-word vue/multi-word-component

问题&#xff1a;搭建脚手架时报错&#xff0c;具体错误如下&#xff1a; ERROR in [eslint] E:\personalProject\VueProjects\vueproject2\src\components\Student.vue10:14 error Component name "Student" should always be multi-word vue/multi-word-compon…

【办公类-52-01】20240703计划小结的缩略版制作(获取字符最多的3个字,删除字后面的内容)

背景需求&#xff1a; 每学期写完“信息计划”“信息小结”都需要上传园所“圆圆通”的信息公开&#xff0c;领导要求使用缩略版&#xff08;就是删掉一些内容&#xff0c;不能整篇都发布出去&#xff0c;以免被抄袭&#xff1f;&#xff09; 2023年第二学期的信息小结有16页 …

CX1概念车空气动力学设计,打造典型“美式肌肉车”风格

Altair CX1概念车的设计 CX1是Altair公司为了满足汽车行业的设计和虚拟仿真需求而开发的一款概念车型。该车总长接近5米&#xff0c;外观具有典型的美式肌肉车的风格&#xff0c;具有视觉冲击力。 车辆的外形设计过程就是风险管理&#xff0c;设计师想要一个大胆而富有表现力的…

赢麻了!苹果再获OpenAI董事会观察员席位!0元白嫖ChatGPT,比肩微软

今年&#xff0c;苹果和OpenAI的合作有点密切。 据最新消息&#xff0c;苹果获得OpenAI的董事会观察员席位。 苹果应用商店负责人、前营销主管菲尔席勒&#xff08;Phil Schiller&#xff09;将担任这一职位&#xff0c;但Schiller迄今为止尚未出席任何OpenAI的会议。 观察员…

C语言刷题小记

前言 本篇博客和大家分享一些C语言的OJ题目&#xff0c;希望大家可以通过这些题目进一步提升自己的编程能力&#xff0c;如果你对本篇内容感兴趣&#xff0c;可以一键三连&#xff0c;多多关注&#xff0c;下面进入正文部分。 题目1 十六进制转十进制 描述 BoBo写了一个十六…

firewalld(6)自定义services、ipset

简介 在前面的文章中我们已经介绍了zone、rich rule 、--direct等功能和基本配置。在前面文章中&#xff0c;我们提到过firewalld内置了很多服务&#xff0c;可以通过firewall-cmd --get-services来查看服务&#xff0c;也可以通过配置文件查看这些服务/var/lib/firewalld/ser…

【Unity 角色控制器组件】

【Unity 角色控制器组件】 Character Controller&#xff1a; Unity 内置的一个组件&#xff0c;用于提供高级的物理控制&#xff0c;允许开发者控制角色的移动、跳跃和碰撞。 csharp csharp // 假设你已经有了一个带有Character Controller组件的游戏对象// 获取Character Co…

In Ictu Oculi: Exposing AI Created Fake Videos by Detecting Eye Blinking

文章目录 In Ictu Oculi: Exposing AI Created Fake Videos by Detecting Eye Blinking背景关键点内容预处理Long-Term Recurrent CNNsLSTM-RNN模型训练实验data启示In Ictu Oculi: Exposing AI Created Fake Videos by Detecting Eye Blinking 会议:2018 IEEE International…

容嬷嬷给紫薇过生日:鬼畜搭台,AI带货

刚入7月&#xff0c;短视频平台已被AI视频续写占领。 类似于紫薇在地牢里被容嬷嬷喂西瓜、喂鸡翅、喂蛋糕。张学友在《旺角卡门》的经典镜头突然给你微笑、嘟嘴、甚至祝你生日快乐。甚至&#xff0c;还有吴京从打斗戏变成亲吻戏。 在AI续写的短视频里&#xff0c;你永远也想象…

【最新综述】医学图像分割深度半监督学习(上)

摘要&#xff1a; 最近&#xff0c;深度学习在各种计算机视觉任务中展现出了巨大的前景。然而&#xff0c;在许多实际应用中&#xff0c;没有大规模的标记数据集&#xff0c;这限制了深度学习的应用。为了解决这个问题&#xff0c;半监督学习引起了计算机视觉界的广泛关注&…

二叉树的前中后序遍历(递归法、迭代法)leetcode144、94/145

leetcode144、二叉树的前序遍历 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,2,3] 示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;[] 示例 3&#xff1a; 输…

CesiumJS【Basic】- #057 绘制纹理填充多边形(Primitive方式)

文章目录 绘制纹理填充多边形(Primitive方式)1 目标2 代码2.1 main.ts绘制纹理填充多边形(Primitive方式) 1 目标 使用Primitive方式绘制绘制纹理填充多边形 2 代码 2.1 main.ts import * as Cesium from cesium;const viewer = new Cesium.Viewer

测试Andrew NG的语言翻译Agent

我正在测试 Andrew Ng 的语言翻译 A​​I 代理系统及其在逆变换下的稳定性。 给定源语言的文本&#xff0c;我们应用翻译函数 f&#xff0c;然后应用 f 的逆。它应该是不变的&#xff1a; 但是&#xff0c;数学与语言翻译有什么关系&#xff1f; 在完美的系统中&#xff0c;从…

springboot异常产生原因

DataIntegrityViolationException Cause: java.sql.SQLException: Field ‘id’ doesn’t have a default value org.springframework.dao.DataIntegrityViolationException: ### Error updating database. Cause: java.sql.SQLException: Field id doesnt have a default …

[译]全栈Redux实战

本文乱译自一篇英文博文&#xff08;Full-Stack Redux Tutorial&#xff09;&#xff0c;本人英语能力不足&#xff0c;技术能力有限&#xff0c;如有错误&#xff0c;多多包涵。 #关于ReduxReactImmutable的测试先行开发综合指南 Redux是最近发生在js界令人兴奋的事儿。它把…

提升Unity WebGL游戏启动速度

一、查看启动耗时 通过修改unity-namespace.js中hideTimeLogModal为false&#xff0c;显示timelog开发者可以看到小游戏目前的启动首屏时长&#xff1a; 将其设置为false后&#xff0c;启动小程序后就会显示启动耗时 要知道各个阶段的含义&#xff0c;我们必要理解启动流程。 …