【Typescript】知识梳理:函数

556 阅读4分钟

函数声明和函数表达式

JavaScript 中,有两种常见的定义函数的方式:函数声明(Function Declaration)和函数表达式(Function Expression)。

在 TypeScript 中,要对输入和输出进行约束,输入多余的(或者少于要求的)参数,都是不被允许的。

// 函数声明(Function Declaration)
function sum(x: number, y: number): number {
    return x + y;
}
​
// 函数表达式(Function Expression)
//推断类型
let mySum = function (x: number, y: number): number {
    return x + y;
};
//完整类型
let myAdd: (baseValue: number, increment: number) => number =
    function(x: number, y: number): number { return x + y; };
//在 TypeScript 的类型定义中,=> 用来表示函数的定义,而ES6 中,=> 叫做箭头函数。

可选参数

与接口中的可选属性类似,用 ? 表示可选的参数。可选参数必须接在必需参数后面。

function buildName(firstName: string, lastName?: string) {
    if (lastName) {
        return firstName + ' ' + lastName;
    } else {
        return firstName;
    }
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName('Tom');

参数默认值

在 ES6 中,我们允许给函数的参数添加默认值,TypeScript 会将添加了默认值的参数识别为可选参数

添加默认值,不受可选参数必须接在必需参数后面的限制。

function buildName(firstName: string = 'Tom', lastName: string) {
    return firstName + ' ' + lastName;
}
let tomcat = buildName('Tom', 'Cat');
let cat = buildName(undefined, 'Cat');

剩余参数

ES6 中,可以使用 ...rest 的方式获取函数中的剩余参数(rest 参数),剩余参数语法允许将一个不确定数量的参数作为一个数组传入。

//Typescript
function buildName(firstName: string, ...restOfName: string[]) {
    return firstName + " " + restOfName.join(" ");
}
  
let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");

重载

利用联合类型,不能够精确的表达,即输入输出类型不能一一对应。重载允许一个函数接受不同数量或类型的参数时,作出不同的处理。

如果参数类型不同,则参数类型应设置为 any。参数数量不同可以将不同的参数设置为可选。

注意,TypeScript 会优先从最前面的函数定义开始匹配,所以多个函数定义如果有包含关系,需要优先把精确的定义写在前面。

参数类型不同:

function disp(string):void; 
function disp(number):void;

参数数量不同:

function disp(n1:number):void; 
function disp(x:number,y:number):void;

参数类型顺序不同:

function disp(n1:number,s1:string):void; 
function disp(s:string,n:number):void;

用接口定义函数的形状

采用函数表达式|接口定义函数的方式时,对等号左侧进行类型限制,可以保证以后对函数名赋值时保证参数个数、参数类型、返回值类型不变。

interface SearchFunc {
    (source: string, subString: string): boolean;
}
​
let mySearch: SearchFunc;

mySearch = function(source: string, subString: string) {
    return source.search(subString) !== -1;
}

匿名函数

匿名函数是一个没有函数名的函数。

匿名函数在程序运行时动态声明,除了没有函数名外,其他的与标准函数一样。

将匿名函数赋值给一个变量,这种表达式就成为函数表达式。

var res = function(a:number,b:number) { 
    return a*b;  
}; 
console.log(res(12,2))

匿名函数自调用(在函数后使用 () 即可):

(function () { 
    var x = "Hello!!";   
    console.log(x)     
 })()

构造函数

TypeScript 支持使用 JavaScript 内置的构造函数 Function() 来定义函数。

通过new 函数名来实例化对象的函数叫构造函数。任何的函数都可以作为构造函数存在。之所以有构造函数与普通函数之分,主要从功能上进行区别的,构造函数的主要功能为初始化对象,特点是和new一起使用。new就是在创建对象,从无到有,构造函数就是在为初始化的对象添加属性和方法。构造函数定义时首字母大写(规范)。

对new理解:new 申请内存, 创建对象,当调用new时,后台会隐式执行new Object()创建对象。所以,通过new创建的字符串、数字是引用类型,而是非值类型。

ES6 class的写法实质就是构造函数。class 为构造函数的语法糖,即class的本质是构造函数。class的继承 extends本质为构造函数的原型链的继承。通过class定义的类和通过构造函数定义的类二者本质相同。并且在js执行时,会将第一种转会为第二种执行。

语法格式如下:

var res = new Function ([arg1[, arg2[, ...argN]],] functionBody)

参数说明:

  • arg1, arg2, ... argN:参数列表。
  • functionBody:一个含有包括函数定义的 JavaScript 语句的字符串。
var myFunction = new Function("a", "b", "return a * b"); 
var x = myFunction(4, 3); 
console.log(x);

递归函数

递归函数即在函数内调用函数本身。

使用递归的时候,函数是声明式的写法,避免出现 test is not a function 这种错误

function factorial(number) {
    if (number <= 0) {         // 停止执行
        return 1; 
    } else {     
        return (number * factorial(number - 1));     // 调用自身
    } 
}; 
console.log(factorial(6));      // 输出 720

Lambda 函数

Lambda 函数也称之为箭头函数。

箭头函数表达式的语法比函数表达式更短。

单个参数 () 是可选的,无参数时可以设置空括号。

函数只有一行语句:

( [param1, parma2,…param n] )=>statement;
//实例
var foo = (x:number)=>10 + x 
console.log(foo(100))      //输出结果为 110