1. 程式人生 > >《前端之路》- TypeScript(二) 函式篇

《前端之路》- TypeScript(二) 函式篇

[TOC] ### 一、定義函式方法 > 在 es5 中定時函式的方法有 命名函式和函式表示式(匿名函式)這門兩種。那麼同樣的,在 TypeScript 中,函式的定義是什麼樣子的呢? #### 1-1 命名函式 這裡需要注意的一點是: viod 型別,是函式不返回任何型別資料 > `TypeScript` 語法 ```typescript function func1(): string { return '213'; } function func2(): number { return 123; } function func3(): Array { return [123, {}]; } function func4(): Array { return [123, 456]; } function func5(): Array { return ['123', '1233']; } function func6(): void { console.log(123); } ``` > 被編譯成 `ES5` 的 `JavaScript` ```javascript "use strict"; function func1() { return '213'; } function func2() { return 123; } function func3() { return [123, {}]; } function func4() { return [123, 456]; } function func5() { return ['123', '1233']; } function func6() { console.log(123); } ``` #### 1-2 函式表示式 這裡需要簡單的普及一個 ES6 的箭頭函式,無大括號時,直接表示 return 這個值。 > `TypeScript` 語法 ```typescript const fun11 = (): string => { return '123'; }; const fun12 = (): string => '123'; const fun13 = (): any => [123, '123']; const fun14 = function(): string { return '123'; }; const fun15 = function(): any { return { name: 123 }; }; ``` > 被編譯成 `ES5` 的 `JavaScript` ```javascript "use strict"; var fun11 = function () { return '123'; }; var fun12 = function () { return '123'; }; var fun13 = function () { return [123, '123']; }; var fun14 = function () { return '123'; }; var fun15 = function () { return { name: 123 }; }; ``` ### 二、定義函式傳參 #### 2-1 定義函式傳參 這裡需要簡單的描述下,函式的傳參的型別和之前文章中介紹到的資料型別定義方式是一致的。 > `TypeScript` 語法 ```typescript const parasFun1 = (x: string, y: number) => { console.log(x + y); }; let res1 = parasFun1('1', 2); // 猜猜返回啥?哈哈哈哈 可以子啊留言中寫下你的答案 ``` > 被編譯成 `ES5` 的 `JavaScript` ```javascript "use strict"; var parasFun1 = function (x, y) { console.log(x + y); }; var res1 = parasFun1('1', 2); // 猜猜返回啥?哈哈哈哈 可以子啊留言中寫下你的答案 ``` ### 三、可選傳參 #### 3-1 定義函式的可選傳參 這裡需要簡單的描述下,函式的可選引數,很明顯就是可以選擇傳入這個引數也可以選擇不傳入這個引數,且可選引數一定是排在必傳引數的後面。 > `TypeScript` 語法 ```typescript const parmaFunc1 = (name: string, age?: number) => { if (age) { return `我的名字是:${name} --- 我的年齡是: ${age}`; } else { return `我的名字是:${name} --- 我的年齡保密!`; } }; let res11 = parmaFunc1('zhangsan', 123); let res12 = parmaFunc1('zhangsan'); const parmaFunc2 = (name?: string, age: number) => { if (age) { return `我的名字是:${name} --- 我的年齡是: ${age}`; } else { return `我的名字是:${name} --- 我的年齡保密!`; } }; // 這裡的 parmaFunc2 會報錯麼? ``` > 被編譯成 `ES5` 的 `JavaScript` ```javascript "use strict"; var parmaFunc1 = function (name, age) { if (age) { return "\u6211\u7684\u540D\u5B57\u662F\uFF1A" + name + " --- \u6211\u7684\u5E74\u9F84\u662F\uFF1A " + age; } else { return "\u6211\u7684\u540D\u5B57\u662F\uFF1A" + name + " --- \u6211\u7684\u5E74\u9F84\u4FDD\u5BC6\uFF01"; } }; var res11 = parmaFunc1('zhangsan', 123); var res12 = parmaFunc1('zhangsan'); ``` ### 四、預設傳參 #### 4-1 定義函式預設傳參 這裡的預設傳參和 ES6 中預設傳參的使用方式是一致的 > `TypeScript` 語法 ```typescript const defaultParamFunc1 = (x: string, age: number = 10): void => { console.log(`我的名字是:${name} --- 我的年齡是: ${age}`); }; let defaultRes1 = defaultParamFunc1('zhangsan'); // 這裡會打印出什麼呢? ``` > 被編譯成 `ES5` 的 `JavaScript` ```javascript "use strict"; var defaultParamFunc1 = function (x, age) { if (age === void 0) { age = 10; } console.log("\u6211\u7684\u540D\u5B57\u662F\uFF1A" + name + " --- \u6211\u7684\u5E74\u9F84\u662F\uFF1A " + age); }; var defaultRes1 = defaultParamFunc1('zhangsan'); ``` ### 五、傳遞剩餘引數 #### 5-1 定義函式傳遞剩餘引數(三點運算子) 這裡的傳遞剩餘引數和 ES6 中傳遞剩餘引數的使用方式是一致的,只不過我們可能需要對剩餘引數進行一個型別的定義 > `TypeScript` 語法 ```typescript // 寫一個demo 就是,我們需要對一個對個求和,且我們不知道具體會有多少個引數 const restParamsFunc1 = (x: any, y: any, z: any): number => { return x + y + z; }; let restRes1 = restParamsFunc1(1, 2, 3); // 正常執行 // let restRes2 = restParamsFunc1(1, 2, 3, 4); // ts 會報錯,說第四個引數未宣告 const restParamsFunc2 = (...res: number[]): number => { let sum = 0; for (let index = 0; index < res.length; index++) { sum += res[index]; } return sum; }; let restRes3 = restParamsFunc2(1, 2, 3, 4); // 這個時候又會得出什麼結果呢? ``` >
被編譯成 `ES5` 的 `JavaScript` ```javascript "use strict"; // 寫一個demo 就是,我們需要對一個對個求和,且我們不知道具體會有多少個引數 var restParamsFunc1 = function (x, y, z) { return x + y + z; }; var restRes1 = restParamsFunc1(1, 2, 3); // 正常執行 // let restRes2 = restParamsFunc1(1, 2, 3, 4); // ts 會報錯,說第四個引數未宣告 var restParamsFunc2 = function () { var res = []; for (var _i = 0; _i < arguments.length; _i++) { res[_i] = arguments[_i]; } var sum = 0; for (var index = 0; index < res.length; index++) { sum += res[index]; } return sum; }; var restRes3 = restParamsFunc2(1, 2, 3, 4); // 這個時候又會得出什麼結果呢? ``` ### 六、函式過載 #### 6-1 JavaScript 中的函式過載 >
函式名稱相同,但是函式的傳入引數不同。執行不同的功能,這個時候就會出現函式過載。 > `TypeScript` 語法 ```typescript const reloadFunc1 = (name: string) => { console.log(name); }; const reloadFunc1 = (age: string) => { console.log(age); }; const reloadFunc1 = (name: string, age: number) => { if (age) { console.log(name, age); } else { console.log(name); } }; // 這個時候我們會發現 ts 已經給我們報了語法的錯誤,但是轉譯成 es5 的程式碼的時候依然可以執行,只不過後面定義的方式會覆蓋前面定義的同名函式的方法 ``` >
被編譯成 `ES5` 的 `JavaScript` ```javascript "use strict"; var reloadFunc1 = function (name) { console.log(name); }; var reloadFunc1 = function (age) { console.log(age); }; var reloadFunc1 = function (name, age) { if (age) { console.log(name, age); } else { console.log(name); } }; // 這個時候我們會發現 ts 已經給我們報了語法的錯誤,但是轉譯成 es5 的程式碼的時候依然可以執行,只不過後面定義的方式會覆蓋前面定義的同名函式的方法 ``` > 這裡我們需要區分一下 Java 中的函式過載和 ts 中的函式過載的區別 - 在 Java 中 定義的同名過載函式,會根據傳入資料型別的差異,直接執行對應的函式,但是 ts 不會。 - 在 ts 中,即使定義了過載函式,編譯成 ES5 以後,還是隻剩下一個對應函式的判斷。這裡我們只做一個簡單的瞭解,在前端寫 JS 的時候還是需要注意名稱空間和命名重疊的問題。 > 我們還是以程式碼的例子來做區分,例子一如下: > `TypeScript` 語法 ```typescript const reloadFunc2 = (name: string):string; const reloadFunc2 = (age: number):number; const reloadFunc2 = (age:any):any => { if(typeof age === 'number') { console.log(name, age) } else { console.log(name) } } // 這個時候,ts 依然會報錯,是為什麼? 這裡就要提到 const 、let 的作用域的問題,因為這裡也是 ES6 的基礎知識,不展開來說了。 ``` > 被編譯成 `ES5` 的 `JavaScript` ```javascript var reloadFunc2 = function (name) { return ; }; var reloadFunc2 = function (age) { return ; }; var reloadFunc2 = function (age) { if (typeof age === 'number') { console.log(name, age); } else { console.log(name); } }; ``` > 我們還是以程式碼的例子來做區分,例子二如下: > `TypeScript` 語法 ```typescript function reloadFunc3(name: string):string; function reloadFunc3(age: number):number; function reloadFunc3(str:any):any { if(typeof str === 'number') { console.log(name, str) } else { console.log(name) } }; ``` > 被編譯成 `ES5` 的 `JavaScript` ```javascript function reloadFunc3(str) { if (typeof str === 'number') { console.log(name, str); } else { console.log(name); } } // 這裡編譯出來,居然只有一個函式,驚歎了,為什麼驚歎了呢?因為這裡和 Java 中的函式過載差別有點大。 ``` ### 七、箭頭函式 #### 7-1 定義箭頭函式 > 箭頭函式的話,其實和 ES6 中的寫法是一致的,然後需要我們注意的是,箭頭函式中的上下文,指向的是起父級函式的上下文。 > `TypeScript` 語法 ```typescript const arrowFunc = (): number => { return 123; }; setTimeout(() => { console.log('過了一秒'); }, 1000); ``` > 被編譯成 `ES5` 的 `JavaScript` ```javascript "use strict"; var arrowFunc = function () { return 123; }; setTimeout(function () { console.log('過了一秒'); }, 1000); ``` ### 八、總結 > 這一篇文章也只能算是基礎入門級別的 ts 中函式的定義方式和方法,這個需要大家在日常的專案中多書寫,才能避免一些問題,然後我們就會發現,我們在使用 ts 去書寫一些函式和對應引數的時候,我們已經可以避免一些多餘引數和錯誤的引數型別的傳入導致的一些奇奇怪怪的bug。好了,這一章就先寫到這裡。 --- > GitHub 地址:(歡迎 star 、歡迎推薦 : ) > [《前端之路》 - TypeScript(二)函式篇](https://github.com/erbing/blog/blob/master/%E5%89%8D%E7%AB%AF%E4%B9%8B%E8%B7%AF%20-%20TypeScript/%E4%BA%8C%E3%80%81typeScript%E4%B8%AD%E7%9A%84%E5%87%BD%E6%95