星期三, 1月 22, 2014

TypeScript 函式 (三)

之前我們談過了 TypeScript 的型別了,今天來談談 TypeScript 的函式(Function)。Bibby 在學 JavaScript 的過程中,函式是我最早使用到,一開始就只用函式處理前端的簡單運算,然後在 HTML 裡呼叫,在網際網路還很單純的年代,這樣寫就很無敵了..

<input type="submit" value="submit" onclick="confirm('確定')" />

function confirmMsg(msg){
    if(confirm(msg)){
        return true;
    }
    return false
}

不過時代的變遷,前端的複雜度已經超乎想像,以前的寫法不是說不能用,是如果專案很大,很多人一起共同開發,或是前端的程式越來越複雜,這種寫法就不適合,模組化(module)的需求及立即函式(IIFE)寫法就開始會用在專案上了,這部份之後再花時間討論,今天來看一下 TypeScript 函式的部份

命名函式(named function) 和匿名函式(anonymous function)
 
在 TypeScript 裡,函式有命名函式(named function)跟匿名函式(anonymous function),這跟 JavaScript 是一樣的

//named function
function Hello(name) {
    console.log("Hello, " + name);
}
//anonymous function
var myHello= (name) => {
    console.log("Hello, " + name);
};

不過在寫 TypeScirpt 函式時,通常不會這樣寫,因為 TypeScript 是有型別的,應該要把型別加進去,讓程式更嚴謹一點,會在參數還有回傳值部份加入型別,這樣 TypeScript 編譯器在儲存時就會去檢查型別是否如預期的這樣

//named function
function Hello(name: string): void {
    console.log("Hello, " + name);
}
//anonymous function
var myHello= (name: string): void => {
    console.log("Hello, " + name);
};

但是 TypeScript 編譯器是很聰明的,型別推斷會自行判斷回傳的型別為何,所以實務通常不會在所有地方加上型別

function Hello(name: string) {
    console.log("Hello, " + name);
}
var myHello = (name: string) => {
    console.log("Hello, " + name);
};
var myHello1: (name: string) => void = (name) => {
    console.log("Hello, " + name);
};

可選(option)和預設(default)參數

接下來,來看一下參數這一部份,一般的寫法

function Test(param1: string, param2: string, param3: string) {
    console.log(param1 + param2 + param3);
}
Test("AAA", "BBB", "CCC");

在 C# 或是一些近代的語言,對於函式的參數都有可選(option)和預設(default)這些便利的特性,TypeScript 也有提供,如果要使用可選(option)參數的方式,可以使用關鍵字 "?" 這樣寫

function Test(param1: string, param2: string, param3?: string) {
    if (param3)
        console.log(param1 + param2 + param3);
    else
        console.log(param1 + param2);
}
Test("AAA", "BBB", "CCC");
Test("AAA", "BBB");

那如果要用預設值(default)的方式,直接在參數後面加上 "=" 多少值

function Test(param1: string, param2: string, param3= "123") {
    console.log(param1 + param2 + param3);
}
Test("AAA", "BBB", "CCC");
Test("AAA", "BBB");

Rest Parameters
 
有時候,在設計函式時是,因為需要靈活而無法估計有多少參數的,C# 可以用 params 的前贅詞來使用,JavaScript 可以用 arguments 來處理,在 TypeScript 裡也有支援這種方式,關鍵是在參數加上前贅詞"..."來宣告參數,型別為 Array

function GoGoGo(param1: string, param2: string, ...paramN: string[]) {
    console.log(param1, paramN.join(""));
}
GoGoGo("AAA", "BBB", "CCC","DDD");
GoGoGo("AAA", "BBB", "CCC");
GoGoGo("AAA", "BBB");

多載(overload)
 
JavaScript 的函式裡,沒有型別的概念,參數要怎麼給都行,所以本質裡就是多載(overload)的感覺,只需要在函式內部處理好各個參數型別和是否有輸入的問題就行,在 TypeScript 裡,寫法會有點點不同,會把各個預期的參數輸入值先宣告,讓最後一個函式做統一處理

function GoGoGo(x: number, ...y: number[])
function GoGoGo(x: string)
function GoGoGo(x: { Name: string; Age: number })
function GoGoGo(x: any, ...y: number[]) {
    if (typeof x == "number") {
        var all = 0;
        for (var i = 0; i < y.length; i++) {
            all += y[i];
        }
        console.log(x + all);
    }

    if (typeof x == "string") {
        console.log(x);
    }

    if (typeof x == "object") {
        console.log("Name:" + x.Name + ", Age:" + x.Age);
    }
}
GoGoGo(1, 3, 5, 7, 9);
GoGoGo("TestTest");
GoGoGo({ Name: "Bibby", Age: 21 });

以上就是 TypeScript 對於函式的一些特性,TypeScript 在函式的部份,原則上跟原生的 JavaScript 沒有相差太多,對於函式的寫法一些改良,加入一些特性,讓程式寫的更不容易出錯也更直覺。

下一篇,來聊聊 TypeScript 的 Interface

Reference
http://www.typescriptlang.org/

沒有留言: