函数可以看作是一种对现实客观规律的抽象,是对某种具体问题的建模。
1.1 定义函数
函数是一个独立的作用域,函数体中可以包含多条语句,并作为一个整体一起执行。在typescript中可以用几种方式定义函数:
1.1.1 函数声明
声明函数必须加function关键字。
function add(x:number, y:number):number {
return x + y;
}
1.1.2 函数表达式
函数表达式从语法上看是将函数声明赋值给一个变量。在函数表达式中,函数名可以省略,此时函数就是匿名函数。
let a = function(x:number, y:number): number {
return x + y;
}
1.1.3 箭头函数表达式
es6的语法,在这里不细说,主要是它也是一个匿名函数,优点是更简短的函数定义且不绑定this。
let a = (x:number, y:number) => {
return x + y;
}
1.1.4 Function对象
所有函数都应看做Function类的实例,Function对象可以定义任何函数,new Function(参数)来创建函数。但一般不用,因为定义函数比其他方式慢的多。
let fnHello = new Function("msg", "console.log(\"Hello \" + msg);")
1.2 调用函数
1.2.1 函数模式
函数声明一般为命名函数,可以通过函数名直接调用;函数表达式和箭头函数表达式一般为匿名函数,需要通过表达式名来调用。
函数模式是函数调用的基本方式。
函数声明创建的函数会被提升,可以在函数声明前调用该函数,但是函数表达式和箭头函数不会被提升。
console.log(add1(1, 2)); // 3
// 函数声明提升
function add1(x:number, y:number): number {
return x + y;
}
console.log(add2(2, 3)); // 运行时报错,add2 is not a function
var add2 = function(x:number, y:number): number {
return x + y;
};
console.log(add3(4, 5)); // 运行时报错,add3 is not a function
var add3 = (x:number, y:number) => {
return x + y;
};
1.2.2 方法模式
函数可以添加到对象中,相当于对象的行为,此时函数就是方法。
let obj = {
add: function(x:number, y:number): number {
return x + y;
}
}
console.log(obj.add(5, 6));
这里当用匿名函数赋值给方法时,this为调用它的对象,当用箭头函数表达式赋值给方法,this指向对象的父级中的this对象。不好理解的话,可以理解为匿名函数执行方法所在的对象,箭头函数指向window(不绝对)。
1.2.3 构造器模式
函数除了可以直接调用,还可以通过new的方法来调用,此时相当于把函数当构造函数来使用。
1.2.4 上下文模式
上下文模式主要是利用函数的call和apply方法改变某个函数运行时的上下文,换句话说,就是为了改变函数体内的this具体指向对象。
bind也可以对函数进行调用,它会创建一个新函数,称为绑定函数。
1.3 函数的参数及其分类
1.3.1 可选参数
可选参数使用问号标识(?)来定义。
function func(a: string, b?: string) {
return a + " " + b;
}
let result1 = func("jack");
let result2 = func("jack", "leo");
函数的参数可以全部设为可选的,但可选的必须位于非可选参数之后,否则报错。
1.3.2Rest参数(剩余参数)
Rest参数可以接受函数的多余参数,组成一个数组,但必须放在形参的最后面,其之前用…表示。
function func(a: string, ...b: string[]) {
return a + " " + b;
}
let result1 = func("jack");
let result2 = func("jack", "adams", "swith");
1.3.3 默认参数
函数的参数默认值是在参数声明后用等号(=)来设置的。
function getDiscount(price: number, rate: number = 0.5) {
let discount = price * number;
return discount;
}
1.3.4 类型注解
typescript是一种静态类型语言,这让我们可以对变量和函数参数进行类型注解(type annotation),类型注解也就是对参数或变量进行注释,比如限定参数为数值类型或者字符类型。
类型注解用于强制类型检查,可以用冒号(:)在函数参数名后面指定类型。
let stu: {
id: string,
age: number,
name: string
}
function print(student: {
id: string,
age: number,
name: string
}) {
console.log(student.name);
}
stu = {
id: "001",
age: 16,
name: "jacl"
}
print(stu);
1.4 特殊函数
1.4.1 匿名函数
顾名思义,匿名函数就是没有函数名的函数,即function关键字后直接小括号。使用场景一般是:
1、即刻自调用
2、回调函数
3、对象的方法
1.4.2 构造函数
构造函数用于创建对象时初始化对象,即为对象成员变量赋初始值。构造函数总是与new操作符一起使用,也支持使用内置的构造函数Function()来定义函数。
Function()构造函数允许运行时代码动态的创建和编译,在这个方式上类似于全局函数eval()。Function()构造函数每次执行时都解析函数主体,创建一个新的函数对象。所以效率很低,不建议使用。
1.4.3 递归函数
1.4.4 lambda函数(箭头函数)
1.4.5 函数重载
函数重载用来实现功能类似但所处理的数据类型不同的问题,函数重载函数名相同,但参数不同,返回类型可以不同也可以相同。
函数重载是多态的一种实现方式。JavaScript本身不支持重载,typescript用变通的方式实现的:先声明所有函数重载的定义,不包含方法的实现,再声明函数体的内容,只需要一次,通过参数不同做判断编写函数体。
// 声明定义
function disp(x: string);
function disp(x: number);
// 实现
function disp(x: any) {
if (typeof x === "string") {
...
} else if (typeof x === "number") {
...
} else {
...
}
}
函数重载声明定义必须放在实现函数之前。