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