TS函数类型

news2024/11/18 15:38:12

函数类型表达式

function hello(x: string) {
  console.log(x)
}
//greeter函数的参数是一个函数fn,fn也有一个string类型参数,无返回值。
function greeter(fn: (a: string) => void) {
  fn('hello')
}
greeter(hello)

也可以把定义参数类型的语句单独提取出来。

function hello(x: string) {
  console.log(x)
}
type Hello = (a: string) => void
function greeter(fn: Hello) {
  fn('hello')
}
greeter(hello)

调用签名

上述例子描述了函数可调用性,此外,函数还具有属性。函数表达式不能声明函数的属性,如果我们想描述函数可以做什么,可以为函数设置属性,及调用签名。

type DescriptionFunction = {
  //函数的属性和属性的类型
  description: string
  //(函数参数名:参数类型):函数返回值类型
  (someArg: number): boolean
}
function doSomething(fn: DescriptionFunction) {
  console.log(fn.description + 'returned' + fn(4))
}

function test(someArg: number) {
  return someArg > 3
}
test.description = 'haha'
doSomething(test)

同理你可以自己添加其他属性和参数

type DescriptionFunction = {
  description: string
  total: number
  (someArg: number, otherArg: string): string
}
function doSomething(fn: DescriptionFunction) {
  console.log(fn.description + fn.total + 'returned' + fn(4, 'other'))
}

function test(someArg: number, other: string) {
  return someArg + other
}
test.total = 0
test.description = '函数的描述属性'
doSomething(test)

构造签名

在调用签名中可以使用new关键字来编写构造签名。

type SomeConstructor = {
  new (a: string): object//笼统的说,函数类型是new(string类型的参数),返回值是一个object
}
function constructObj(fn: SomeConstructor) {
  return new fn('string')//调用时也不能少new关键字。
}

可选参数、以及函数参数不同和返回值不同等情况都会导致函数类型不同,你可以使用这些特性来定义一个复杂的函数类型。

//需要保证每种定义不重合。
interface CallOrConstruct {
  (n?: number): string//这个函数可以是不接收参数或接收number参数,并返回string的类型
  (x: string): boolean//这个函数可以是接收string参数返回boolean值的类型
  new (s: string): Date//这个函数可以是构造函数,并且需要接收一个string参数,返回Date值。
}
function doSomeing(fn: CallOrConstruct) {
  //这里只是举例调用,具体能怎么调用,还得看传过来的fn参数带来一些什么样的参数。
  fn(1)
  fn('string')
  new fn('2022-06-01')
}

你可以将上面例子类比于我们经常使用的Date。传时间戳的时候它给我们返回一个时间格式字符串,传某个时间字符串并使用new关键字的时候,他会给我们返回一个日期对象。

泛型函数

当我们的输出类型与输入类型相关时,我们就可以使用泛型函数。
定义方法:使用尖括号定义泛型名称,放在函数名和函数括号中间,现在你可以把定义的泛型类似于一个已知的基础类型来用,用来定义参数和返回值的类型。

function test<Type>(x: Type[]): Type | undefined {
  return x[0]
}
const t1 = test(['1', '2', '3'])//const t1: string | undefined
const t2 = test([1, 2, 3])//const t2: number | undefined
const t3 = test([])//const t3: undefined

你可以使用多个泛型变量
下面编写一个map函数。接收一个数组和一个函数,函数内对接收的数据进行操作,返回值是一个数组。

function myMap<Input, Output>(arr: Input[], func: (a: Input) => Output): Output[] {
  return arr.map(func)//这里调用的是公共的js中的map函数
}
//  const test1: number[]
//在第一个测试案例中,Input类型是number,Output类型是number,返回值类型是number[]
const arr1 = [1, 2, 3]
const test1 = myMap(arr1, (item) => item + 1)
//  const test2: string[]
//在第二个测试案例中,Input是object,output是string,返回值类型是string[]
const arr2 = [
  { id: '12', age: 12 },
  { id: '23', age: 34 }
]
const test2 = myMap(arr2, (item) => item.id)

TypeScript 可以根据函数表达式的返回值推断 Input 类型参数的类型以及 Output 类型参数。
第一次调用myMap,myMap的类型推断为:

function myMap<number, number>(arr: number[], func: (a: number) => number): number[]

第二次调用myMap,myMap的类型推断为:

function myMap<{id: string;age: number;}, string>(arr: {id: string;age: number;}[], func: (a: {id: string;age: number;}) => string): string[]

类型约束

泛型函数可以处理任何类型的值。有时候,我们有两个类型相关的值,但是我们只能操作他的子属性,我们就可以使用类型约束。
下面的test1和test2的类型是根据参数推断出来的。泛型就是将两个或多个具有相同类型的值关联起来!

interface hasLength {
  length: number
}
function longer<Type extends hasLength>(a: Type, b: Type) {
  if (a.length > b.length) return a
  else return b
}
const test1 = longer([1, 2], [1, 2, 3])
const test2 = longer('dfs', 'fdjask')
//const test3 = longer(10, 11)//error,number类型没有length属性

使用约束值的错误

泛型定义的是一种类型,光满足约束的条件不行,还得是真真确确的类型。
让我们看下面这个例子,泛型Type进行了约束,返回值也是Type类型。

function minimumLength<Type extends { length: number }>(obj: Type, minimum: number): Type {
  if (obj.length >= minimum) {
    return obj
  } else {
    return { length: minimum } //error 不能将类型“{ length: number; }”分配给类型“Type”。
  }
}

假设上面的语法合发,将会得到一个完全行不通的代码。

function minimumLength<Type extends { length: number }>(obj: Type, minimum: number): Type {
  if (obj.length >= minimum) {
    return obj
  } else {
    return { length: minimum } //error 不能将类型“{ length: number; }”分配给类型“Type”。
  }
}
//obj.length<minimum,return { length : 4 }
const arr = minimumLength([1, 2, 3], 4)
const x = arr.slice(0)//行不通

分析得知,尽管对象中有length属性,但是对象根本没有slice方法。

指定类型参数

下面是一个将两个数组合并的函数。

function combine<Type>(a: Type[], b: Type[]): Type[] {
  return a.concat(b)
}
combine([1, 2], [3, 4])
combine(['1', '2'], ['3', '4'])
combine([1, 2], ['3', '4'])//error Type已经推断为number类型,后面不能再传string类型的数组了

第三个测试案例中,由于 Type已经推断为number类型,后面不能再传string类型的数组了。
这个时候我们就可以手动指定类型参数的值,而不是让TypeScript给我们默认推断。

//combine([1, 2], ['3', '4'])
combine<number | string>([1, 2], ['3', '4'])

当我们把代码改为上述模样后,可以发现combine的类型推断变为:
实质上这个时候Type的类型就是string|number。

function combine<string | number>(a: (string | number)[], b: (string | number)[]): (string | number)[]

编写良好的泛型函数指南

下推类型参数

如果可以,使用类型参数本身而不是约束它。

function test1<Type>(arr: Type[]) {
  return arr[0]
}
function test2<Type extends any[]>(arr: Type) {
  return arr[0]
}
//const t1: number
const t1 = test1([1, 2, 3])
//const t2: any
const t2 = test2([1, 2, 3])

显然,第一种写法比第二种写法要好,第一种写法可以推断出返回值的类型,而第二种写法推断的类型是any。
我们尽量直接使用类型,而不做类型约束。

使用更少的类型参数

如果可以,始终使用尽可能少的类型参数。
例如写一个过滤函数时,下面第一种写法只定义了一个类型参数,剩下的都是利用这个类型灵活使用,最终调用也能准确地推断出返回值地类型。

function filter1<Type>(arr: Type[], func: (arg: Type) => boolean): Type[] {
  return arr.filter(func)
}
const t1 = filter1([-1, 2, 3], (item) => item > 0)

对于第二种写法,这里多写了一个类型参数Func,还对Func做了类型限制,用起来两者得到的结果是一样的,但是,Func并没有关联两个或多个值的类型,它没有做任何事情,只会让读者更难理解。

function filter2<Type, Func extends (arg: Type) => boolean>(arr: Type[], func: Func): Type[] {
  return arr.filter(func)
}
const t2 = filter2([-1, 2, 3], (item) => item > 0)

类型参数应该出现两次

如果一个类型参数只出现在一个位置,强烈重新考虑是否真的需要它

有时候我们可能忘了函数是不需要泛型的。

function greet<Str extends string>(s: Str) {
  console.log("Hello, " + s);
}
greet("world");

我们可以更容易地编写一个更简单的版本。

function greet(s: string) {
  console.log("Hello, " + s);
}

泛型用于关联多个值的类型。如果一个泛型只在函数签名中使用一次,它就没有任何关系。这包括推断的返回类型;
例如,如果 Str 是 greet 的推断返回类型的一部分,它将关联参数和返回类型,因此尽管在书面代码中只出现一次,但它会被使用两次。

可选参数

//问号,可传可不传,可传undefined
function f1(n?: number): void {
  console.log(n)
}
f1()
f1(1)
f1(undefined)

//指定默认值
function f2(x: number = 10) {
  console.log(x)
}
f2(1)

回调中的可选参数

为回调编写函数类型时,切勿编写可选​​参数,除非你打算在不传递该参数的情况下调用该函数。
如果你在函数类型中声明了一个参数为可选参数,那么在使用这个函数类型时,传递该参数是可选的。如果你不打算在调用函数时传递该参数,但是却在函数类型中将其声明为可选参数,可能会导致一些问题。
这会导致:你有可能传递了可选参数,但是函数里面没有没有调用。或者,你没传递可选参数,但是函数里面调用了。这带来了一些难以查找的错误。

function myForEach(arr: any[], callback: (arg: any, index?: number) => void) {
  for (let i = 0; i < arr.length; i++) {
    // callback(arr[i], i)
    callback(arr[i])
  }
}
myForEach([1, 2, 3], (item) => console.log(item))
myForEach([1, 2, 3], (item, index) => console.log(item, index))

函数重载

我们希望可以以各种参数、参数个数、参数类型来调用函数。这可以使用函数重载来实现。
函数签名一定多于两个。
函数只有一个实现签名,但是这个签名不能直接调用。
函数的调用是按照函数的重载签名定义来的,下面两个函数签名中,只有传递一个参数的,或者传递三个参数的。最后一种调用,传递了两个参数,是不可行的。

//函数的重载签名
function makeDate(timestamp: number): Date
function makeDate(m: number, d: number, y: number): Date
//函数的实现签名
function makeDate(mOrTimestamp: number, d?: number, y?: number): Date {
  if (d !== undefined && y !== undefined) {
    return new Date(y, mOrTimestamp, d)
  } else {
    return new Date(mOrTimestamp)
  }
}
//这里调用的都是函数的重载签名,不是函数的实现签名
const d1 = makeDate(1798329749)
const d2 = makeDate(6, 11, 2022)
//error没有需要 2 参数的重载,但存在需要 1 或 3 参数的重载
//const d3 = makeDate(1, 2)

重载签名和实现签名

重载签名:没有方法体,只有函数名、函数参数及类型、函数返回值及类型。
实现签名:兼容所有函数签名,有方法体。
从外部看不到实现的签名。在编写重载函数时,你应该始终在函数实现之上有两个或多个签名。
实现签名还必须与重载签名兼容。
例如,下面这个例子,就是实现签名与重载签名在函数参数类型不兼容。

function fn(x: boolean): void;
function fn(x: string): void;//error此重载签名与其实现签名不兼容
function fn(x: boolean) {}

稍微改动一下实现签名的函数参数即可:

function fn(x: boolean | string) {}

下面这个例子是实现签名与重载签名在返回值类型部分不兼容。

function fn(x: string): string;
function fn(x: number): boolean;
function fn(x: string | number) {
  return "oops";
}

同样,改动一下实现签名的返回值类型即可:

function fn(x: string | number): string | boolean {
  return 'oops'
}

需要注意的是,上面的改动,能使函数正常调用,但是函数调用的时候,不能传递一个不确定类型的值。例如,fn(Math.random() > 0.5 ? 'dfs' : true)
这将会导致报错,原因:TypeScript只会将函数调用解析为一种重载。传递可能值,会混淆TypeScript的判读。

编写好的重载

尽可能使用联合类型的参数而不是重载。
下面是一个返回字符串或数组长度的函数。

function len(s: string): number
function len(arr: any[]): number
function len(x: any) {
  return x.length
}
len('')
len([0])
len(Math.random() > 0.5 ? 'hello' : [0]) //error没有与此调用匹配的重载。

我们不能使用可能是字符串或数组的值来调用函数重载,因为TypeScript只能将函数调用解析为单个重载。
我们将函数改为非重载版本即可。

function len(x: any[] | string) {
  return x.length;
}

在函数中声明this

TypeScript 将通过代码流分析推断函数中的 this 应该是什么。

interface DB {
  filterUsers(filter: (this: User) => boolean): User[];
}
 
const db = getDB();
const admins = db.filterUsers(function (this: User) {
  return this.admin;
});

这种模式在回调风格的 API 中很常见,其中另一个对象通常控制何时调用你的函数。
请注意,你需要使用 function 而不是箭头函数来获得此行为。

其他需要了解的类型

void

void 表示不返回值的函数的返回值。只要函数没有任何 return 语句,或者没有从这些返回语句返回任何显式值,它就是推断类型。

function test1() {
  return
} //function test1(): void

function test2() {
  console.log('')
} //function test2(): void

在 JavaScript 中,不返回任何值的函数将隐式返回值 undefined。但是,void 和 undefined 在 TypeScript 中不是一回事。

object

特殊类型 object 指的是任何非基础值(string、number、bigint、boolean、symbol、null 或 undefined)。
object和{}不同。
object和Object也不同,在TypeScript中,你可能永远用不到Object。
在JavaScript中,函数值是对象:它们有属性,在它们的原型链中有 Object.prototype,是 instanceof Object,你可以在它们上调用 Object.keys,等等。
在 TypeScript 中,函数类型被视为 object。

unknown

unknown类型代表任何值,作用类似于any类型,但是比any类型安全,因为使用unknown做任何事情都是不合法的。
在这里插入图片描述
你可以描述一个返回未知类型值的函数,而不需要使用any。

function safeParse(s: string): unknown {
  return JSON.parse(s)
}

never

有些函数从不返回值,可以使用never定义返回值类型。

function fail(msg: string): never {
  throw new Error(msg)
}

never 类型表示从未观察到的值。在返回类型中,这意味着函数抛出异常或终止程序的执行
TypeScript确定联合中没有任何类型时,也会返回never。

function fail(msg: string): never {
  throw new Error(msg)
}
function fn(x: string | number) {
  if (typeof x === 'string') {
    console.log(x) //(parameter) x: string
  } else if (typeof x === 'number') {
    console.log(x) // (parameter) x: number
  } else {
    console.log(x) // (parameter) x: never
  }
}

Function

全局类型 Function 描述了 bind、call、apply 等属性,以及 JavaScript 中所有函数值上的其他属性。
它还具有 Function 类型的值始终可以被调用的特殊属性;这些调用返回 any。

function test(f: Function): void {
  const x = f(1, 2, 3) //const x: any
}

这是不安全的,如果函数可以接收任何类型的参数,且不需要返回值,那么建议用()=>void替换Function。

剩余形参和实参

剩余形参

除了使用可选参数或重载来制作可以接受各种固定参数计数的函数之外,我们还可以使用剩余参数定义接受无限数量参数的函数。
剩余参数出现在所有其他参数之后,并使用 … 语法
让我们来分析下面这段代码。其中m就是10,n就是1,2,3,4组成的数组。
返回值:n的所有数乘以m再返回一个数组,最终结果为:[10,20,30,40]

function multiply(m: number, ...n: number[]) {
  return n.map((item) => item * m)
}
const a = multiply(10, 1, 2, 3, 4)

剩余实参

相反,我们可以使用扩展语法从可迭代对象(例如数组)中提供可变数量的参数。例如,数组的 push 方法接受任意数量的参数:

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
arr1.push(...arr2);

TypeScript 并不假定数组是不可变的。
下面这段代码就会报错,atan2是一个只接收两个参数的函数,TypeScript认为args是可变的,故TypeScript不允许将一个可变的数组传递给一个只能接收两个参数的函数。

const args = [8, 5]
const angle = Math.atan2(...args)

这种情况使用as const就可以解决了。

const args = [8, 5] as const
const angle = Math.atan2(...args)

参数解构

你可以使用参数解构来方便地将作为参数提供的对象解包到函数体中的一个或多个局部变量中。
和JavaScript中的解构差不多,就是多了类型的定义。

type ABC = { a: number; b: number; c: number }
function sum({ a, b, c }: ABC) {
  console.log(a + b + c)
}
sum({ a: 1, b: 2, c: 3 })

函数的可赋值性

返回类型void

具有 void 返回类型 (type voidFunc = () => void) 的上下文函数类型,当实现时,可以返回任何其他值,但会被忽略。
因此,下列写法是有效的。

type voidFunc = () => void

const f1: voidFunc = () => {
  return true
}
const f2: voidFunc = () => true
const f3: voidFunc = function () {
  return true
}
const v1 = f1();//const v1: void
const v2 = f2();//const v1 = f1()
const v3 = f3();//const v1 = f1()

我们可以发现,尽管TypeScript允许我们在函数类型的返回类型为void的情况下返回其他值,但是我们返回的值是不生效的。

当字面量函数定义具有 void 返回类型时,该函数不得返回任何内容。

function f2(): void {
  return true //不能将类型“boolean”分配给类型“void”
}

const f3 = function (): void {
  return true //不能将类型“boolean”分配给类型“void”
}

注意,这里的void是我们手动加在函数上的,是函数的返回类型。上面的voidFunc,是我们定义的某种函数的类型。
上面是直接定义整个函数的类型,下面定义的是函数的返回值类型。

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

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

相关文章

【Java程序设计】【C00376】基于(JavaWeb)Springboot的社区帮扶对象管理系统(有论文)

【C00376】基于&#xff08;JavaWeb&#xff09;Springboot的社区帮扶对象管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;已经做了六年的毕业设计程序开发&am…

SD-WAN海外专线:全球企业网络的增强利器

企业在全球范围内建立高效、安全的网络连接至关重要。云桥通SD-WAN海外专线是一种先进的网络解决方案&#xff0c;正在受到越来越多企业的青睐。 提升网络性能和稳定性 SD-WAN海外专线结合了SD-WAN和专用专线服务的优势&#xff0c;能够显著提高网络性能和稳定性。通过智能路由…

Spring Cloud四:微服务治理与安全

Spring Cloud一&#xff1a;Spring Cloud 简介 Spring Cloud二&#xff1a;核心组件解析 Spring Cloud三&#xff1a;API网关深入探索与实战应用 文章目录 一、服务注册中心的选型与最佳实践1. 主流服务注册中心概述2. 最佳实践建议(1)、选型建议(2)、高可用性与稳定性1). 高可…

哪些属于“法律、行政法规另有规定,依照其规定进行评估/批准”的情况?

哪些属于“法律、行政法规另有规定&#xff0c;依照其规定进行评估/批准”的情况&#xff1f; 除《网络安全法》《数据安全法》和《个人信息保护法》确立的数据和网络安全整体体系外&#xff0c;企业还应当考虑其他相关法律法规的要求。 例如&#xff1a; ✮如根据《中华人民…

【 yolo红外微小无人机-直升机-飞机-飞鸟目标检测】

yolo无人机-直升机-飞机-飞鸟目标检测 1. 小型旋翼无人机目标检测2. yolo红外微小无人机-直升机-飞机-飞鸟目标检测3. yolo细分类型飞机-鸟类-无人机检测4. yolo红外大尺度无人机检测5. 小型固定翼无人机检测6. 大型固定翼无人机检测7. yolo航空俯视场景下机场飞机检测 1. 小型…

js逆向之实例某宝热卖(MD5)爬虫

目录 正常写 反爬 逆向分析 关键字搜索 打断点&分析代码 得出 sign 的由来 确定加密方式 写加密函数了 补全代码 免责声明:本文仅供技术交流学习,请勿用于其它违法行为. 正常写 还是老规矩,正常写代码,该带的都带上,我这种方法发现数据格式不完整. 应该后面也是大…

这些好玩的Ai网站你不知道我真的会哭

你可能想不到&#xff0c;AI已经发展到了这个程度。。文末提供 AI绘画关键词哦 目录 1.Midjourney 2.DeepFakes 3.StyleGAN 4.Runway AI绘画关键词哦 1.Midjourney Midjourney 是一款工具&#xff0c;更像是一位魔术师&#xff0c;但它的魔法来自人工智能技术的神奇。…

C语言中位运算介绍

在C语言中&#xff0c;位运算是一种对二进制位进行操作的运算方式&#xff0c;它可以对数据的二进制表示进行位级别的操作&#xff0c;包括按位与、按位或、按位异或、按位取反等。位运算常用于处理底层数据结构、优化代码性能以及实现各种算法。本文将深入介绍C语言中的位运算…

从汇编以及栈帧层面理解内联函数的原理

宏太复杂&#xff0c;所以弄出内联&#xff0c;内联适合小函数&#xff0c;把函数连到程序里面&#xff0c;这样就直接用&#xff0c;不需要调用&#xff0c;但是它占用空间。 C推荐 const和enum替代宏常量 inline去替代宏函数 宏缺点&#xff1a; 1、不能调试 2、没有类型安…

发现了一本超厉害的英语秘籍,绝对YYDS

昨天冷月小姐姐分享了一本书&#xff0c;她说是一位英语大神发她的。 我也打开了&#xff0c;很酷炫。 群友们也在与时俱进&#xff0c;随手截图&#xff0c;分享了大模型对文档的理解。 你可能会想&#xff0c;关注宏观经济有啥用&#xff0c;自己只是大海中的浪花一朵。 还有…

vue+Echarts实现多设备状态甘特图

目录 1.效果图 2.代码 3.注意事项 Apache ECharts ECharts官网&#xff0c;可在“快速上手”处查看详细安装方法 1.效果图 可鼠标滚轮图表和拉动下方蓝色的条条调节时间细节哦 &#xff08;注&#xff1a;最后一个设备没有数据&#xff0c;所以不显示任何矩形&#xff09;…

苹果手机突然黑屏打不开怎么办?多种方法合集

苹果手机突然黑屏无法打开是让人感到焦虑和困扰的常见问题。当遇到这种情况时&#xff0c;很多用户会感到手足无措&#xff0c;不知道该如何应对。苹果手机突然黑屏打不开怎么办&#xff1f;本文汇总了多种解决苹果手机突然黑屏打不开问题的方法&#xff0c;论是常见的手机重启…

Ceph——部署

Ceph简介 Ceph是一款开源的 SDS 分布式存储&#xff0c;它具备极高的可用性、扩展性和易用性&#xff0c;可用于存 储海量数据 Ceph的存储节点可部署在通用服务器上&#xff0c;这些服务器的 CPU 可以是 x86 架构的&#xff0c;也可以 是 ARM 架构的。 Ceph 存储节点之间相互…

国内ip怎么来回切换:操作指南与注意事项

在数字化时代&#xff0c;互联网已经成为我们日常生活、学习和工作中不可或缺的一部分。然而&#xff0c;随着网络应用的不断深化&#xff0c;用户对于网络环境的稳定性和安全性要求也越来越高。其中&#xff0c;IP地址作为网络中的关键标识&#xff0c;其切换与管理显得尤为重…

软件产品在哪个阶段容易产生缺陷

软件产品在哪个阶段容易产生缺陷 软件缺陷由许多原因造成&#xff0c;如果把这些缺陷按照整个软件研发周期归纳起来&#xff0c;统计发现&#xff0c;需求规格说明书是软件存在缺陷最多的地方。 软件研发周期&#xff1a;需求文档->需求规格说明书->设计文档->编码-&g…

Pillow教程04:学习ImageDraw+Font字体+alpha composite方法,给图片添加文字水印

---------------Pillow教程集合--------------- Python项目18&#xff1a;使用Pillow模块&#xff0c;随机生成4位数的图片验证码 Python教程93&#xff1a;初识Pillow模块&#xff08;创建Image对象查看属性图片的保存与缩放&#xff09; Pillow教程02&#xff1a;图片的裁…

大数据分析案例-基于决策树算法构建大学毕业生薪资预测模型

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

Web开发基本流程

Web是全球广域网&#xff0c;能够通过浏览器访问的网站。我们要访问网站&#xff0c;首先要在浏览器输入对应的域名。 浏览器也是一个程序&#xff0c;京东的网站也是一个程序&#xff0c;在京东那边电脑运行着&#xff0c;我们只是通过浏览器远程访问。京东的程序由三个部分组…

Redis入门到实战-第十六弹

Redis实战热身Cuckoo filter篇 完整命令参考官网 官网地址 声明: 由于操作系统, 版本更新等原因, 文章所列内容不一定100%复现, 还要以官方信息为准 https://redis.io/Redis概述 Redis是一个开源的&#xff08;采用BSD许可证&#xff09;&#xff0c;用作数据库、缓存、消息…

Java毕业设计-基于springboot开发的学生就业管理系统-毕业论文+答辩PPT(附源代码+演示视频)

文章目录 前言一、毕设成果演示&#xff08;源代码在文末&#xff09;二、毕设摘要展示1、开发说明2、需求分析3、系统功能结构 三、系统实现展示1、前台功能模块2、后台功能模块2.1 管理员功能2.2 学生功能2.3 企业功能 四、毕设内容和源代码获取总结 Java毕业设计-基于spring…