TypeScript 類和函數(shù)

先看兩篇文章關(guān)于 ES5 原型鏈的蛤虐,寫的特別好党饮,圖畫的就更好了,參考資料:
幫你徹底搞懂JS中的prototype驳庭、proto與constructor(圖解)
詳解JavaScript中的new操作符

忍不住盜圖一張:


原型鏈:f1.__proto__.__proto__.__proto__ === null;

一刑顺、TypeScript 類

1.1 介紹

TypeScript 的 class 和 ES2015 的 class 并不是完全一樣的概念,ES6 的 class 僅僅是一種語法糖饲常,但是這種語法糖已經(jīng)成為標(biāo)準(zhǔn)蹲堂,并且(新)瀏覽器內(nèi)核基本支持,而平時(shí)使用的時(shí)候不皆,基本都是通過 webpack 或者 gulp 這種進(jìn)行兼容或者打包贯城。

而 TypeScript 的 class 可以使得開發(fā)者在不依賴 ES5 的環(huán)境下直接使用,不需要等到下個(gè) JS 版本霹娄。類的形式在 JavaScript 中有兩種寫法能犯,ES5 的類和 ES6 的類,決定 TypeScript 翻譯成哪種在 tsconfig.json 里面配置:

"target": "ESNEXT", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
1.2 TypeScript 類與 ES6 類的不同犬耻。

ES6 的類有 extends 和 static 這點(diǎn)和 TypeScript 沒啥不同踩晶,不同的是 ES6 的屬性修飾符只有默認(rèn)公開屬性和一個(gè)私有屬性(還是在提案中)。私有屬性還和 TypeScript 不同枕磁,使用 # 來定義的渡蜻,官方還給出了理由。

之所以要引入一個(gè)新的前綴#表示私有屬性计济,而沒有采用private關(guān)鍵字茸苇,是因?yàn)?JavaScript 是一門動(dòng)態(tài)語言,沒有類型聲明沦寂,使用獨(dú)立的符號(hào)似乎是唯一的比較方便可靠的方法学密,能夠準(zhǔn)確地區(qū)分一種屬性是否為私有屬性。另外传藏,Ruby 語言使用@表示私有屬性腻暮,ES6 沒有用這個(gè)符號(hào)而使用#彤守,是因?yàn)锧已經(jīng)被留給了 Decorator

ES 和 TS 比除了屬性修飾符不同,沒有抽象類之外哭靖,其他的都差不多具垫。

1.3 屬性修飾符

1、public 默認(rèn)
一些語言的默認(rèn)屬性修飾符是 protected试幽,而 TypeScript 中成員屬性默認(rèn)都是 public筝蚕,除了默認(rèn)之外,也可以強(qiáng)制手動(dòng)指定铺坞。

特點(diǎn)是:可以被繼承饰及、外部實(shí)例和內(nèi)部 this 可以訪問
2、private 私有屬性

特點(diǎn)是:只能內(nèi)部訪問
3康震、protected
構(gòu)造函數(shù)如果使用 protected 聲明燎含,說明這個(gè)類不能被實(shí)例化,只能被繼承腿短。

特點(diǎn)是:外部實(shí)例不能訪問
4屏箍、readonly 修飾符
readonly 修飾符用于將屬性設(shè)置為只讀,如果要設(shè)置值橘忱,則只能在聲明或者是在構(gòu)造函數(shù)中初始化內(nèi)容赴魁。
5、參數(shù)屬性
定義的屬性可以賦值默認(rèn)值钝诚,不在構(gòu)造函數(shù)進(jìn)行初始化颖御。

1.4 抽象類

抽象類作為其他子類的基類,一般不進(jìn)行直接實(shí)例化凝颇,特別的像接口潘拱,但和接口不同的是,抽象類可以去實(shí)現(xiàn)成員屬性或者是方法拧略,然后子類再去覆寫成員屬性或者方法芦岂。

abstract class Person {
    abstract talk(): void;
    walk(): void {
        console.log('...')
    }
}

和其他高級(jí)語言的面向?qū)ο蟪橄箢愐粯樱绻粋€(gè)方法被定義為 abstract(抽象方法)垫蛆,則這個(gè)方法可以不在基類中實(shí)現(xiàn)禽最,但是它的子類必須去實(shí)現(xiàn)這個(gè)方法。抽象方法必須在抽象類里面袱饭。

abstract class Person {
    abstract talk(): void;
    walk(): void {
        console.log('...')
    }
}
new Person();//不允許川无,直接報(bào)錯(cuò)
class Male extends Person{ 
    talk(){}//必須有這個(gè)
}
1.5 TypeScript 類的其他知識(shí)

去參考:http://es6.ruanyifeng.com/#docs/class

二、函數(shù)

TypeScript 的函數(shù)主要增加了強(qiáng)類型判斷和一個(gè)函數(shù)重載知識(shí)點(diǎn)虑乖。

2.1 函數(shù)類型

下面兩個(gè)函數(shù)聲明了參數(shù)的類型以及函數(shù)返回值的類型,上面是具名函數(shù)懦趋,下面是匿名函數(shù)

function add(x: number , y: number ): number {
   return x + y;
}

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

雖然上面已經(jīng)定義了函數(shù)的類型,但是匿名函數(shù)并沒有定義完整的函數(shù)類型决左,完整的函數(shù)類型:

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

完整的函數(shù)類型包括:參數(shù)類型返回值類型

首先聲明了參數(shù)類型 :(x: number, y: number) 愕够,然后聲明了返回值類型 => number =

而參數(shù)的名字實(shí)際上可以不一致佛猛,上面示例中雖然寫了相同的名字惑芭,但是可以寫成兩個(gè)不同的參數(shù)名稱:

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

返回值類型通過 => 進(jìn)行表示,如果一個(gè)函數(shù)返回值是 void 继找,也必須聲明是 void遂跟,不能省略因?yàn)橥暾暮瘮?shù)類型包含參數(shù)類型和返回值類型兩個(gè)部分,一個(gè)也不能省略婴渡。

let myAdd: (x1: number, y1: number) => void  = function (x: number, y: number) : number {
    return x + y;
}

函數(shù)的類型只是由參數(shù)類型和返回值組成的幻锁。

函數(shù)中使用的捕獲變量不會(huì)體現(xiàn)在類型里。 實(shí)際上边臼,這些變量是函數(shù)的隱藏狀態(tài)并不是組成API的一部分哄尔。

所謂的捕獲變量,與函數(shù)本身是無關(guān)的柠并,因?yàn)檫@個(gè)是由函數(shù)作用域外(父級(jí)作用域或更高級(jí)作用域)聲明的變量岭接,只是在函數(shù)中使用了而已。

const a:number = 1;
let add:(x: number) => number = function(x: number) :number {
    return a + x;
}
推斷類型

完整的函數(shù)類型中臼予,需要我們明確標(biāo)示參數(shù)的類型是什么鸣戴,但是如果兩邊的參數(shù)中只有一邊的參數(shù)聲明了類型,typescript 會(huì)嘗試去識(shí)別類型:

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

上面代碼中粘拾,因?yàn)?baseValueincrement 已經(jīng)聲明了類型是 number窄锅,所以 x 和 y 會(huì)推斷出類型是 number。

2.2 可選參數(shù)和默認(rèn)參數(shù)

TypeScript 里的每個(gè)函數(shù)參數(shù)都是必須的缰雇,這不是指不能傳遞 nullundefined 作為參數(shù)入偷,而是說編譯器檢查用戶是否為每個(gè)參數(shù)都傳入了值。

編譯器還會(huì)假設(shè)只有這些參數(shù)會(huì)被傳遞進(jìn)函數(shù)械哟。

簡(jiǎn)短地說盯串,傳遞給一個(gè)函數(shù)的參數(shù)個(gè)數(shù)必須與函數(shù)期望的參數(shù)個(gè)數(shù)一致。

function add(x: number, y: number) :number {
    return x + y;
}

add(1,2);
add(1); // 錯(cuò)誤
add(1,2,3); // 錯(cuò)誤

上面 add 方法的使用中戒良,后面兩種都是錯(cuò)誤的体捏,因?yàn)閭魅氲膮?shù)個(gè)數(shù)與期望的個(gè)數(shù)不相符合

如果需要聲明某個(gè)參數(shù)是可選參數(shù),則可以通過 ? 來標(biāo)示:

function add(x:number, y:number, z?: number): number {
    z = z || 0;
    return x + y + z;
}

上面代碼中通過 z? 聲明 z 可選參數(shù)糯崎,因此傳入 2 個(gè)或者3個(gè)參數(shù)都是可以的几缭。

然而上面代碼為了兼容 z 沒有值得時(shí)候,寫了個(gè)默認(rèn)值處理 z = z || 0沃呢,而 ES6 有了函數(shù)參數(shù)默認(rèn)值特性之后年栓,這種寫法基本都是被廢棄的,在 TypeScript 中薄霜,可以使用同樣的方式聲明函數(shù)參數(shù)的默認(rèn)值:

function add(x:number, y:number, z:number = 0): number {
    return x + y + z;
}

add(1, 3);
add(1,2,3);
add(1,2,3,4)

而一旦聲明了默認(rèn)值之后某抓,就表示這個(gè)值可有可無纸兔,類似于已經(jīng)加了 z? 聲明。

需要注意的是否副,可選參數(shù)必須接在必需參數(shù)后面汉矿。換句話說,可選參數(shù)后面不允許再出現(xiàn)必需參數(shù)了

2.3 剩余參數(shù)

ES6 同樣擁有 rest 參數(shù)备禀,也就是剩余參數(shù)洲拇。它可以表示任意剩下的參數(shù),本質(zhì)是一個(gè)數(shù)組曲尸。

typescript 中同樣通過省略號(hào)來表示剩下的多個(gè)參數(shù):

function add(x: number, ...otherNum:number[]): number {
   otherNum && otherNum.forEach((item) => {
    x += item;
  });
   return x;
}
add(1, 3, 4, 54, 5, 6);
2.4 重載

重載:允許一個(gè)函數(shù)接受不同數(shù)量或類型的參數(shù)時(shí)赋续,作出不同的處理。比如另患,我們需要實(shí)現(xiàn)一個(gè)函數(shù) reverse纽乱,輸入數(shù)字 123 的時(shí)候,輸出反轉(zhuǎn)的數(shù)字 321昆箕,輸入字符串 'hello' 的時(shí)候迫淹,輸出反轉(zhuǎn)的字符串 'olleh'。
利用聯(lián)合類型为严,我們可以這么實(shí)現(xiàn):

function reverse(x: number | string): number | string {
    if (typeof x === 'number') {
        return Number(x.toString().split('').reverse().join(''));
    } else if (typeof x === 'string') {
        return x.split('').reverse().join('');
    }
}

然而這樣有一個(gè)缺點(diǎn)敛熬,就是不能夠精確的表達(dá),輸入為數(shù)字的時(shí)候第股,輸出也應(yīng)該為數(shù)字应民,輸入為字符串的時(shí)候,輸出也應(yīng)該為字符串夕吻。
這時(shí)诲锹,我們可以使用重載定義多個(gè) reverse 的函數(shù)類型:

function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string {
    if (typeof x === 'number') {
        return Number(x.toString().split('').reverse().join(''));
    } else if (typeof x === 'string') {
        return x.split('').reverse().join('');
    }
}

上例中,我們重復(fù)定義了多次函數(shù) reverse涉馅,前幾次都是函數(shù)定義归园,最后一次是函數(shù)實(shí)現(xiàn)。在編輯器的代碼提示中稚矿,可以正確的看到前兩個(gè)提示庸诱。

但是需要注意的是重載函數(shù)只是兩個(gè)函數(shù)聲明,并沒有函數(shù)體晤揣。所以上面雖然有三個(gè)函數(shù)但是只有兩個(gè)重載函數(shù)桥爽。

TypeScript 會(huì)優(yōu)先從最前面的函數(shù)定義開始匹配,所以多個(gè)函數(shù)定義如果有包含關(guān)系昧识,需要優(yōu)先把精確的定義寫在前面钠四。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市跪楞,隨后出現(xiàn)的幾起案子缀去,更是在濱河造成了極大的恐慌侣灶,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缕碎,死亡現(xiàn)場(chǎng)離奇詭異褥影,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)阎曹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來煞檩,“玉大人处嫌,你說我怎么就攤上這事≌迮龋” “怎么了熏迹?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長凝赛。 經(jīng)常有香客問我注暗,道長,這世上最難降的妖魔是什么墓猎? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任捆昏,我火速辦了婚禮,結(jié)果婚禮上毙沾,老公的妹妹穿的比我還像新娘骗卜。我一直安慰自己,他們只是感情好左胞,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布寇仓。 她就那樣靜靜地躺著,像睡著了一般烤宙。 火紅的嫁衣襯著肌膚如雪遍烦。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天躺枕,我揣著相機(jī)與錄音服猪,去河邊找鬼。 笑死拐云,一個(gè)胖子當(dāng)著我的面吹牛蔓姚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播慨丐,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼坡脐,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了房揭?” 一聲冷哼從身側(cè)響起备闲,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤晌端,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后恬砂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體咧纠,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年泻骤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了漆羔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡狱掂,死狀恐怖演痒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情趋惨,我是刑警寧澤鸟顺,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站器虾,受9級(jí)特大地震影響讯嫂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜兆沙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一欧芽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧葛圃,春花似錦渐裸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至诀诊,卻和暖如春洞渤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背属瓣。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來泰國打工载迄, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人抡蛙。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓护昧,卻偏偏與公主長得像,于是被迫代替她去往敵國和親粗截。 傳聞我的和親對(duì)象是個(gè)殘疾皇子惋耙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容