TypeScript學習筆記(四):函數


這篇筆記我們來看看TypeScript中的函數。

函數類型

在JavaScript中存在兩種定義函數的方法,如下:

1 //命名函數
2 function add(x, y) {
3     return x+y;
4 }
5 
6 //匿名函數
7 var myAdd = function(x, y) { return x+y; };

在TypeScript中對應的寫法如下:

1 function add(x: number, y: number): number {
2     return x+y;
3 }
4 
5 var myAdd = function(x: number, y: number): number { return x+y; };

而TypeScript中對函數的類型也可以定義,比如我們上面的myAdd沒有定義類型,則可以將任意類型的函數賦值給它,當然賦值函數以外的東西也可以,這當然是不好的一種做法,我們看看下面的另外一種寫法:

var myAdd: (baseValue:number, increment:number)=>number = 
    function(x: number, y: number): number { return x+y; };

這里我們將myAdd定義為必須是函數,同時必須是帶有兩個number參數返回值為number的函數,其它類型的函數賦值給myAdd會報錯。

定義函數類型

看到這里你是不是煥然大悟了,這不就是C#的委托么?

如果我們在使用到函數類型的地方都采用上面的寫法會比較麻煩,所以可以先定義一個函數類型,在要使用到該類型的地方直接定義為該函數的類型即可,如下:

 1 /**
 2  * 這里可以看做 C# 中的委托.
 3  */
 4 interface IProgressHandler
 5 {
 6     /**
 7      * 進度報告方法.
 8      * @param progress 進度.
 9      * @returns {} 無.
10      */
11     (progress:number):void;
12 }
13 
14 class Loading
15 {
16     private _progressHandler:IProgressHandler;
17 
18     Load(url:string, callback:IProgressHandler)
19     {
20         this._progressHandler = callback;
21         //加載完畢
22         this._progressHandler(1.0);
23     }
24 }
25 
26 function run()
27 {
28     var load: Loading = new Loading();
29     load.Load("http://xxx/", function(p:number):void
30     {
31         alert("加載:" + p);
32     });
33 }
34 
35 run();

可選和默認參數

可選參數,表示該參數可以填寫也可以不填寫,使用?:表示,如下:

 1 function buildName(firstName:string, lastName?:string)
 2 {
 3     if(lastName)
 4         return firstName + " " + lastName;
 5     else
 6         return firstName;
 7 }
 8 
 9 alert(buildName("LiLie"));
10 alert(buildName("Meimei", "Han"));

沒有提供實參則lastName為undefined。

默認參數表示不填該參數則使用提供的默認值,如下:

1 function buildName(firstName:string, lastName:string = "Wang")
2 {
3     return firstName + " " + lastName;
4 }
5 
6 alert(buildName("LiLie"));//LiLie Wang
7 alert(buildName("Meimei", "Han"));//Meimei Han

對象參數類型

我們看一下下面的寫法:

function getArea(quad:Object)
{
    return quad["width"] * quad["height"];
}

alert(getArea({width:10, height:20}));

這種寫法存在一個問題,如果傳入的實參沒有width或height時運行時會報錯但編譯時不會報錯,那么如何才能在編譯時就進行類型判斷呢?

一般其它語言都是使用接口來解決這個問題,但是TypeScript有一種更快捷的方法實現,如下:

1 function getArea(quad:{width:number, height:number})
2 {
3     return quad.width * quad.height;
4 }
5 
6 alert(getArea({width:10, height:20}));

同時也支持可選參數,但不支持默認參數,如下:

 1 function getArea(quad:{width:number, height?:number})
 2 {
 3     if (quad.height == undefined)
 4     {
 5         quad.height = 10;
 6     }
 7     return quad.width * quad.height;
 8 }
 9 
10 alert(getArea({width:10}));

可變參數

可變參數表示可以任意填寫任意參數,如下:

1 function buildName(firstName:string, ...restOfName:string[])
2 {
3     alert(restOfName.length);
4     return firstName + "," + restOfName.join(",");
5 }
6 
7 alert(buildName("LiLie"));
8 alert(buildName("LiLie", "MeimeiHan"));
9 alert(buildName("LiLie", "MeimeiHan", "LinTao", "LaoWang"));

Lambda

簡寫的匿名函數,我們已上門的例子來看:

 1 /**
 2  * 這里可以看做 C# 中的委托.
 3  */
 4 interface IProgressHandler
 5 {
 6     /**
 7      * 進度報告方法.
 8      * @param progress 進度.
 9      * @returns {} 無.
10      */
11     (progress:number):string;
12 }
13 
14 class Loading
15 {
16     private _progressHandler:IProgressHandler;
17 
18     Load(url:string, callback:IProgressHandler)
19     {
20         this._progressHandler = callback;
21         //加載完畢
22         alert(this._progressHandler(1.0));
23     }
24 }
25 
26 function run()
27 {
28     var load: Loading = new Loading();
29     load.Load("http://xxx/", p => {
30         alert("加載:" + p);
31         return "Hello Lambda!";
32     });
33 }
34 
35 run();

TypeScript的Lambda使用和C#中一致。

Lambda和this

我們看一下這個例子:

1 var messenger = {
2     message: "Hello World",
3     start: function() {
4         setTimeout(() => { alert(this.message); }, 3000);
5     }
6 };
7 messenger.start();

編譯后的js如下:

 1 var messenger = {
 2     message: "Hello World",
 3     start: function () {
 4         var _this = this;
 5         setTimeout(function () {
 6             alert(_this.message);
 7         }, 3000);
 8     }
 9 };
10 messenger.start();

更多消息可以查看:http://www.codebelt.com/typescript/arrow-function-typescript-tutorial/

重載

TypeScript的函數支持重載,同名函數可以根據參數類型及數量的不同來執行不同的邏輯,不過定義重載函數和其它語言稍微不同:在TypeScript中需要先寫一些同名的函數聲明,然后在一個同名函數里寫出實現,而且需要自己判斷參數類型(比較雞肋):

 1 function attr(name: string): string;
 2 function attr(name: string, value: string): Accessor;
 3 function attr(map: any): Accessor;
 4 
 5 function attr(nameOrMap: any, value?: string): any {
 6     if (nameOrMap && typeof nameOrMap === "object") {
 7         // handle map case
 8     }
 9     else {
10         // handle string case
11     }
12 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM