04ts中的函数
通過前面JS的學習,想必大家對函數已經非常了解了。 TS 定義函數的方法和 JS 基本一樣,不同的是 TS 可以要求有無返回值。
接下來就介紹一下ts中有關函數的一些東西。
一、函數的定義
? 1.es5定義函數的方法
//函數聲明法function run(){return 'run';}//匿名函數var run2=function(){return 'run2';}2.ts中定義函數
接下來我們同樣寫一個計算兩個數之和的方法:
function total(one: number, two: number) {return one + two; } const total = getTotal(1, 2);這時我們并沒有定義total的返回值類型,雖然TypeScript可以自己推斷出返回值是number類型。 但是如果這時候我們的代碼不小心寫錯了,比如:
function total(one: number, two: number) {return one + two + "i love you"; }const total = total(1, 2);這時候total的值就不是number類型了,但是不會報錯。為了保證我們的結果也是number類型,有的時候你可以這樣寫:
const count: number = total(1, 2);這樣寫雖然可以讓編輯器報錯,但是代碼不夠嚴謹,沒有解決根本原因,這是total()函數的錯誤。所以合適的做法是給函數的返回值加上類型注解。
在ts中需要指定函數的返回值類型。
function total(one: number, two: number): number {return one + two; }const total = total(1, 2);這樣代碼就比較嚴謹了。
二、定義函數返回值
1.ts中定義函數返回值
//函數聲明法function run():string{return 'run';}//錯誤寫法function run():string{return 123;} //匿名函數var fun2=function():number{return 123;}alert(fun2()); /*調用方法*/2.函數無返回值
? 類型為:void
function run():void{console.log('run'); //只打印出‘run’,沒有返回值}run();3.never返回類型
never返回類型前面已經介紹過了。 如果一個函數是永遠也執行不完的,就可以定義返回值為never,那什么樣的函數是永遠也執行不完的那?比如執行的時候,拋出了異常,這時候就無法執行完了。
function errF(): never {throw new Error();console.log("this is error"); }還有一種是一直循環,也是我們常說的死循環,這樣也運行不完,比如下面的代碼:
function forever(): never {while (true) {}console.log("Hello,honey"); }三、函數參數
- 可選參數
- 默認參數
- 剩余參數
1.ts中方法傳參
方法傳參剛才已經提到了,在傳參的時候指定參數的類型:
function getInfo(name:string,age:number):string{return `${name} --- ${age}`;}alert(getInfo('zhangsan',20));2.參數為對象(解構)時
比如我們寫一個對象參數:
function add({ num1, num2 }) {return num1 + num2; }const total = add({ num1: 1, num2: 2 });這時直接報錯了,意思是total有可能會是任何類型,那我們要如何給這樣的參數加類型注解?
function add({ num1: number, num2: number }) {return num1 + num2; } const total = add({ num1: 1, num2: 2 });你在編輯器中會看到這種寫法是完全錯誤的。那正確的寫法應該是這樣的。
function add({ num1, num2}:{num1:number,num2:number}):number {return num1 + num2;}const total = add({ num1: 1, num2: 2 });console.log(total); //3解構一個函數的參數是 對象 的方式是:在后面跟著一個對象類型注解.
如果參數只有一個屬性時,應該這樣寫:
function getcount({ one }: { one: number }): number {return one; }const num = getcount({ one: 1 });3.可選參數
es5里面方法的實參和行參可以不一樣,但是ts中必須一樣,如果不一樣就需要配置可選參數
function getWorker(name:string,age?:number):string{if(age){return `我的名字是:${name} --- 我的年齡是:${age}`;}else{return `我的名字是:${name} --- 我的年齡是保密`;}}console.log(getWorker('孫玉鑫')); //我的名字是:孫玉鑫 --- 我的年齡是保密console.log(getWorker('潘小小',19)); //我的名字是:潘小小 --- 我的年齡是:19注意:可選參數必須配置到參數的最后面
//錯誤的寫法 function getWorker(name?:string,age:number):string{if(age){return `我的名字是:${name} --- 我的年齡是:${age}`;}else{return `我的名字是:${name} --- 我的年齡是保密`;}}console.log(getWorker('譚成銘'));4.默認參數
es5里面沒法設置默認參數,es6和ts中都可以設置默認參數
function getCodeFarmer(name:string,age:number=22):string{if(age==22){return `我的名字是:${name} ---我的年齡是默認值:${age},我是一個碼農`;}else{return `我的名字是:${name} ---我的年齡是:${age},我是一個碼農`;} }console.log( getCodeFarmer('代高飛'));//我的名字是:代高飛 ---我的年齡是默認值:22,我是一個碼農 console.log( getCodeFarmer('高威',15)); //我的名字是:高威 ---我的年齡是:15,我是一個碼農5.剩余參數
剛才我們討論的默認參數和可選參數有個共同點:它們表示某一個參數。 有時,你想同時操作多個參數,或者你并不知道會有多少參數傳遞進來。 在JavaScript里,你可以使用 arguments來訪問所有傳入的參數。在TypeScript里,你可以把所有參數收集到一個變量里。剩余參數會被當做個數不限的可選參數。 可以一個都沒有,同樣也可以有任意個。三點運算符 接受新參傳過來的值。
比如寫一個多個數相加的函數
function sum(a:number,b:number,c:number,d:number):number{return a+b+c+d;}console.log(sum(1,2,3,4))如果還有很多我們不確定的數相加,可以這樣寫:
function sum(...result:number[]):number{var sum=0;for(var i=0;i<result.length;i++){sum+=result[i]; }return sum;}console.log(sum(1,2,3,4,5,6)) ;普通參數可以和剩余參數同時傳遞:
function sum(a:number,b:number,...result:number[]):number{var sum=a+b;for(var i=0;i<result.length;i++){sum+=result[i]; }return sum;}console.log(sum(1,2,3,4,5,6)) ;6.ts函數重載
typescript中的重載:通過為同一個函數提供多個函數類型定義來實現多種功能的目的。
在JS中依據不同參數類型或參數個數執行一些不同函數體的實現很常見,在TypeScript中,會有需要用到這種聲明的地方。
關于函數重載,必須要把精確的定義放在前面,最后函數實現時,需要使用 |操作符或者?操作符,把所有可能的輸入類型全部包含進去,以具體實現。
ts為了兼容es5 以及 es6 重載的寫法和java中有區別。
//es5中出現同名方法,下面的會替換上面的方法 function getName(name){return name;}function getName(name,work){return name+work;}在ts中我們寫一個add函數,它可以接收string類型的參數進行拼接,也可以接收number類型的參數進行相加。
/函數重載 // 聲明 function some (arg1: string, arg2: string): string function some (arg1: number, arg2: number): number// 具體實現 function some (arg1: string | number, arg2: string | number) {// 在實現上我們要注意嚴格判斷兩個參數的類型是否相等,而不能簡單的寫一個 arg1 + arg2if (typeof arg1 === 'string' && typeof arg2 === 'string') {return `拼接兩個字符串:${arg1} + ${arg2}`} else if (typeof arg1 === 'number' && typeof arg2 === 'number') {return arg1 + arg2} }console.log(some("皮皮蝦","跟我走")); //拼接兩個字符串:皮皮蝦 + 跟我走 console.log(some(12,12)); //24 console.log(some("你好",25)) //錯誤 function getUser(name:string):string; function getUser(name:string,age:number):string; function getUser(name:any,age?:any):any{if(age){return '我叫:'+name+'我的年齡是'+age;}else{return '我叫:'+name;} }console.log(getUser('曹西西')); /*正確*/console.log(getUser(123)); //錯誤console.log(getUser('韓尚尚',20)); //正確TypeScript 中的函數重載也只是多個函數的聲明,具體的邏輯還需要自己去寫,它并不會真的將你的多個重名 function 的函數體進行合并。
interface Uodefarmer {name: string;age: number;work:string; }interface ProductManager {name: string;age: number;work:string;rest:string; }declare function doSomething(params: Uodefarmer | ProductManager, flag?: boolean): string;在這個 doSomething函數里,我們的目的是當傳入參數 params是 Uodefarmer(碼農)時,不傳 flag,當傳入 params是 ProductManager(產品經理時) 時,傳入 flag。TypeScript 并不知道這些,當你傳入 params為 Uodefarmer時,flag 同樣允許你傳入:
const user={name:"王沖沖",age:10,work:"碼農"} // 沒有報錯,但是不符合我們的設想doSomething(user,true)使用函數重載能幫助我們實現:
interface Ucodefarmer {name: string;age: number;work:string; }interface ProductManager {name: string;age: number;work:string;rest:string; }declare function doSomething(params: Ucodefarmer): string;declare function doSomething(params: ProductManager, flag: boolean): string;const user={name:"王沖沖",age:10,work:"碼農"}const user2={name:"張三",age:10,work:"碼農",rest:"ahhah" }doSomething(user,true) //errordoSomething(user2,true) //正確函數重載的意義在于能夠讓你知道傳入不同的參數得到不同的結果,如果傳入的參數不同,但是得到的結果(類型)卻相同,那么這里就不要使用函數重載(沒有意義)。如果函數的返回值類型相同,那么就不需要使用函數重載
function func (a: number): number function func (a: number, b: number): number// 像這樣的是參數個數的區別,我們可以使用可選參數來代替函數重載的定義function func (a: number, b?: number): number// 注意第二個參數在類型前邊多了一個`?`// 或是一些參數類型的區別導致的 function func (a: number): number function func (a: string): number// 這時我們應該使用聯合類型來代替函數重載 function func (a: number | string): number總結