TypeScript學習(六):函數的定義及特性

前面我們說完了對象和數組的定義,接下來就是一個重頭戲---函數。函數可謂是在程序猿界無處不在,不管你學什麼語言,都會接觸到函數,我看有的文章將函數定義爲一等公民,這就可以看得出函數對於我們來說地位是多麼的高,是多麼的重要,廢話不多說,我們進入正題。

老樣子,我們先說一下在JavaScript中,對於函數的定義和使用。什麼是函數?函數就是被開發者用來執行某一項或多項功能任務的代碼塊。在JS中定義函數的方式通常有以下幾種:

// 方式1
var sum = function (a, b) {
    return a + b
}

// 方式2
function sum(a, b) {
    return a + b
}

// 方式3
var sum = (a, b) => a + b

// 方式4
var sum = new Function("a", "b", "return a + b")

其中,方式1和方式2比較常見,方式3是ES6中的箭頭函數表達式,這種箭頭函數表達式很好的解決了開發中的this指向問題,後續會出一篇博客單獨講解這個,在這裏就不贅述了,方式4是以構造函數的方式,在實際開發中用的很少,瞭解即可。

下面說一下在typescript中函數的定義方式,結合前面關於對象及數組的定義方式,我們可以採取結合數據類型定義的方式來定義函數(類似於上述JavaScript定義方式2),如下:

// 聲明函數中的輸入和輸出的數據類型
function sum(x: number, y: number): number {
    return x + y;
}

在這裏我們定義了函數sum的輸入和輸出的數據類型,均爲number類型,所以在調用函數的時候必須按照定義的格式嚴格執行,以下調用的方式均爲錯誤方式,如下:

// 情形一:參數比定義的多
function sum(x: number, y: number): number {
    return x + y;
}
sum(1, 2, 3);  // 編譯報錯:Expected 2 arguments, but got 3.

// 情形二:參數比定義的少
function sum(x: number, y: number): number {
    return x + y;
}
sum(1);  // 編譯報錯:Expected 2 arguments, but got 1.

// 情形3:參數類型不是定義的數據類型及其子類型
function sum(x: number, y: number): number {
    return x + y;
}
sum(1, '2');   // 編譯報錯:Argument of type '"2"' is not assignable to parameter of type 'number'.

當然,我們可以寫類似於上述JavaScript中方式一的定義方式來定義函數表達式,如下:

let sum = function (x: number, y: number): number {
    return x + y;
}

上面這樣的寫法沒有錯,但是不夠嚴謹,因爲我們可以看到上面的寫法僅對表達式右邊的函數的類型進行了定義,而沒有對等號左側的進行定義,這樣就類似於我們前面提到的數據類型推論,根據右側的定義來推斷左側的類型,所以,我們可以在定義右側類型的同時,也給左側添加類型,如下:

let sum: (x: number, y: number) => number = function (x: number, y: number): number {
    return x + y;
}

這種定義方式中,可以看到一個熟悉的符號 '=>',瞬間想起了箭頭函數,有木有!!!!!!可惜,這裏的 '=>'跟箭頭函數的那個完全沒關係,在 typescript 的類型定義中,'=>'用來表示函數的定義,左邊是輸入類型,需要用括號括起來,右邊是輸出類型。切記!!!!

我們一直在重複一句話,萬物皆對象,是的,函數也可以用類似於對象接口的定義方式,如下:

// 創建一個Sum的接口,定義輸入輸出數據類型
interface Sum{
    (x: number, y: number): number;
}
// 定義一個函數sum,它的類型是Sum
let sum: Sum;
// 創建函數sum,它的類型要符合接口Sum的定義
sum = function(x: number, y: number) {
    return x + y;
}

typescript的定義就說到這,我們接下來看一下關於typescript中函數的一些特性:

(1)定義函數時,參數可選,而且可選參數必須在後面,如下:

function sum(x: number, y?: number) {   // 切記:可選參數必須放在後面,不然會報錯
    if (y) {
        return x + y;
    } else {
        return x;
    }
}
let sum_1 = sum(1, 2);
let sum_2 = sum(1);

(2)定義函數時,設置默認參數,設置的順序沒有限制,如下:

function sum(x: number, y: number = 3) {
    return x + y
}
let sum_1 = sum(1, 2);
let sum_2 = sum(1);


function sum(x: number = 3, y: number) {
    return x + y
}
let sum_1 = sum(1, 2);
let sum_2 = sum(undefined, 1);  // 注意這裏的參數傳入方式,如果定義默認參數的位置不在後面,那麼我們需要一個佔位的數據變量來佔據輸入參數的位置,而且TS編譯也會報錯:Expected 2 arguments, but got 1.

(3)定義函數時,可以利用...rest來表示剩餘參數,這裏的rest表示的就是參數,如下:

function push(array, ...items) {
    items.forEach(function(item) {
        array.push(item);
    });
}

let a = [];
push(a, 1, 2, 3);

// 這樣看上去比較懵哈,附上編譯好的JS代碼作對比

function push(array) {
    var items = [];
    for (var _i = 1; _i < arguments.length; _i++) {
        items[_i - 1] = arguments[_i];
    }
    items.forEach(function (item) {
        array.push(item);
    });
}
var a = [];
push(a, 1, 2, 3);

(4)重載,就是允許一個函數接受不同數量或類型的參數時,作出不同的處理,也就是允許多類型的參數,我們要利用聯合類型的方法來定義函數,如下:

function getResult(x: number): number;
function getResult(x: string): string;
function getResult(x: number | string): number | string {   // 重載的特性:最後一個相同函數名的會覆蓋之前函數
    if (typeof x === 'number') {
        return x + 2
    } else if (typeof x === 'string') {
        return x + 'kreme'
    }
}

 

 

到底啦!!!!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章