函数
function function_name():return_type {
// 语句
return value;
}
- return_type 是返回值的类型。
- return 关键词后跟着要返回的结果。
- 一般情况下,一个函数只有一个 return 语句。
- 返回值的类型需要与函数定义的返回类型(return_type)一致
函数类型
函数类型包含两部分:参数类型和返回值类型。
// 参数 x 和 y 都是 number 类型,两个参数相加后将其类型转换为 string,
// 所以整个函数的返回值为 string 类型
const add = function(x: number, y: number): string {
return (x + y).toString()
}
// 箭头函数改写
const add = (x: number, y: number): string => (x + y).toString()
函数的完整类型
const add: (x: number, y: number) => string = function(x: number, y: number): string {
return (x + y).toString()
}
//箭头函数改写
//参数位置及类型不变,变量名称可以自己定义,比如把两个参数定位为 a b
const add: (a: number, b: number) => string = (x: number, y: number): string => (x + y).toString()
函数的参数
参数个数保持一致
TypeScript 中每个函数参数都是必须的。 这不是指不能传递 null 或 undefined 作为参数,而是说编译器会检查用户是否为每个参数都传入了值。简短地说,传递给一个函数的参数个数必须与函数期望的参数个数一致。
const fullName = (firstName: string, lastName: string): string => `${firstName}${lastName}`
let result1 = fullName('Sherlock', 'Holmes')
let result2 = fullName(null, undefined)
let result3 = fullName('Sherlock', 'Holmes', 'character') //Error--Expected 2 arguments, but got 3
let result4 = fullName('Sherlock') //Error--Expected 2 arguments, but got 1,An argument for 'lastName' was not provided.
可选参数
在 JavaScript 中每个参数都是可选的,可传可不传。没传参的时候,它的值就是 undefined。
而在 TypeScript 里我们可以在参数名旁使用 ?
实现可选参数的功能,可选参数必须跟在必须参数后面,可选参数后面不允许再出现必需参数。
const fullName = (firstName: string, lastName?: string): string => `${firstName}${lastName}`
let result1 = fullName('Sherlock', 'Holmes')
let result2 = fullName('Sherlock', 'Holmes', 'character') // Error, Expected 1-2 arguments, but got 3
let result3 = fullName('Sherlock') // OK
默认参数
参数可以取默认值,可选参数必须跟在必须参数后面,而带默认值的参数不需要放在必须参数的后面,可随意调整位置:
function buildName(firstName: string, lastName = "Smith") {
return firstName + " " + lastName;
}
console.log(buildName("Bob")) // Bob Smith
console.log(buildName("Bob", undefined)) //Bob Smith
console.log(buildName("Bob", "Adams")) //Bob Adams
剩余参数
当函数的参数个数是不确定的,可能传入未知个数,可以通过 rest 参数
(形式为 ...变量名
)来获取函数的剩余参数,这样就不需要使用 arguments
对象了。
注意 rest 参数 只能是最后一个参数
//第二个参数传入剩余参数,且均为字符串类型
function assert(ok: boolean, ...args: string[]): void {
if (!ok) {
throw new Error(args.join(' '));
}
}
//除第一个参数传入一个布尔类型,后面可以无限传入多个字符串类型的参数
assert(false, '上传文件过大', '只能上传jpg格式')
this 参数
JavaScript 里,this 的值在函数被调用的时候才会被指定,但是这个 this 到底指的是什么还是需要花点时间弄清楚。
默认情况下tsconfig.json
中,编译选项 compilerOptions
的属性 noImplicitThis
为 false
,我们在一个对象中使用的 this 时,它的类型是 any 类型。
let triangle = {
a: 10,
b: 15,
c: 20,
area: function () {
return () => {
// this 为 any 类型
const p = (this.a + this.b + this.c) / 2
//const p = (this.d + this.d + this.d) / 2 改成这样也不会报错,很容易造成不必要的问题。
return Math.sqrt(p * (p - this.a) * (p - this.b) *(p - this.c))
}
}
}
const myArea = triangle.area()
console.log(myArea())
所以我们应该明确 this 的指向
-
第一种,在
tsconfig.json
中,将编译选项compilerOptions
的属性noImplicitThis
设置为true
,TypeScript 编译器就会帮你进行正确的类型推断 -
通过 this 参数 这种形式来解决 this 为 any 类型这一问题。提供一个显式的 this 参数,它出现在参数列表的最前面:
interface Triangle {
a: number;
b: number;
c: number;
area(this: Triangle): () => number;
}
let triangle: Triangle = {
a: 10,
b: 15,
c: 20,
area: function (this: Triangle) {
return () => {
const p = (this.a + this.b + this.c) / 2 //this 指向 Triangle
return Math.sqrt(p * (p - this.a) * (p - this.b) *(p - this.c))
}
}
}
const myArea = triangle.area()
console.log(myArea())
函数重载
函数重载是指函数根据传入不同的参数,返回不同类型的数据。
字符反转问题(不考虑负数情况):
function reverse(target: string | number) {
if (typeof target === 'string') {
return target.split('').reverse().join('')
}
if (typeof target === 'number') {
return +[...target.toString()].reverse().join('')
}
}
console.log(reverse('imooc')) // coomi
console.log(reverse(23874800)) // 847832
编译器并不知道入参是什么类型的,返回值类型也不能确定。这时可以为同一个函数提供多个函数类型定义来进行函数重载。
(通过 --downlevelIteration
编译选项增加对生成器和迭代器协议的支持)
function reverse(x: string): string
function reverse(x: number): number
function reverse(target: string | number) {
if (typeof target === 'string') {
return target.split('').reverse().join('')
}
if (typeof target === 'number') {
return +[...target.toString()].reverse().join('')
}
}
console.log(reverse('imooc')) // coomi
console.log(reverse(23874800)) // 847832
因为这个反转函数在传入字符串类型的时候返回字符串类型,传入数字类型的时候返回数字类型,所以在前两行进行了两次函数类型定义。在函数执行时,根据传入的参数类型不同,进行不同的计算。
为了让编译器能够选择正确的检查类型,它会从重载列表的第一个开始匹配。因此,在定义重载时,一定要把最精确的定义放在最前面。
使用函数时的注意事项
- 如果一个函数没有使用
return
语句,则它默认返回undefined
。 - 调用函数时,传递给函数的值被称为函数的
实参
(值传递),对应位置的函数参数被称为形参
。 - 在函数执行时,
this
关键字并不会指向正在运行的函数本身,而是指向调用函数的对象
。 arguments
对象是所有(非箭头)函数中都可用的局部变量
。你可以使用 arguments 对象在函数中引用函数的参数。