一:Typescript簡(jiǎn)介
維基百科: TypeScript是一種由微軟開發(fā)的自由和開源的編程語言。它是JavaScript的一個(gè)嚴(yán)格超集,并添加了可選的靜態(tài)類型和基于類的面向?qū)ο缶幊獭#的首席架構(gòu)師以及Delphi和Turbo Pascal的創(chuàng)始人安德斯?海爾斯伯格參與了TypeScript的開發(fā)。Typescript是ES6的超集。添加了可選的靜態(tài)類型(注意并不是強(qiáng)類型)和基于類的面向?qū)ο缶幊獭#ㄈ绻麑?duì)ES6熟悉那么可以只關(guān)注類、裝飾器部分的內(nèi)容。)
中文官網(wǎng):https://www.tslang.cn/。
特點(diǎn):微軟開發(fā),javascript超集,遵循ES6標(biāo)準(zhǔn),任何js語法都可以直接在ts里編寫運(yùn)行。Angular2框架是用Typescript開發(fā)的,背景是谷歌和微軟,有可能是未來的前端腳本語言發(fā)展的主流方向。優(yōu)點(diǎn):支持ES6規(guī)范,學(xué)到的typescript語法未來是客戶端腳本語言的主流語法。強(qiáng)大的IDE支持: 1、類型檢查。 2、語法提示。 3、重構(gòu)(修改方法名稱的時(shí)候會(huì)自動(dòng)把引用的地方都重構(gòu))是Angular2的首選開發(fā)語言。
二:環(huán)境搭建
主要是安裝Typescript的代碼編譯器。
本地環(huán)境:一、安裝好nodeJS環(huán)境。二、npm install -g typescript。三、tsc --version。
三:Typescript特性
1. 字符串特性
1.1多行字符串
使用``包裹跨行的字符串,示例:
var html = `<div>
<span></span>
</div>`
1.2:字符串模板
可以在多行字符串中使用模板,示例:
var names = 'daocheng';
function getImg() {
return '<i></i>'
}
var html = `<div>${names}
<span>${getImg()}</span>
<div>
`
1.3:自動(dòng)拆分字符串
function getData(template, name, age) {
console.log(template);
console.log(name);
console.log(age);
}
var names = 'daocheng';
var age = 23;
getData`你好,我的名字是${names},我今年${age}歲了`
2. 參數(shù)新特征
2.1:參數(shù)類型
Typescript中的參數(shù)類型包括:boolean/number/string/array/tuple/enum/any/(null和undefined)/ void /never。其中元祖(tuple)、枚舉、任意值、void類型和never是有別于Javascript的特有類型。
2.2:類型聲明與默認(rèn)參數(shù)
在Typescritpt中聲明變量,需要加上類型聲明,如boolean或string等。通過靜態(tài)類型約束,在編譯時(shí)執(zhí)行類型檢查,這樣可以避免一些類型混用的低級(jí)錯(cuò)誤。示例:
var names = 'daocheng';
function getData(name: stirng, age: number): boolean {
return true
}
Typescript還支持初始化默認(rèn)參數(shù)。如果函數(shù)的某個(gè)參數(shù)設(shè)置了默認(rèn)值,當(dāng)該函數(shù)被調(diào)用時(shí),如果沒有給這個(gè)參數(shù)傳值或者傳值為undefined時(shí),這個(gè)參數(shù)的值就是設(shè)置的默認(rèn)值。示例:
function max(x: number, y: number = 4): number {
return x > y ? x : y;
}
let result1 = max(2); //正常
let result2 = max(2, undefined); //正常
let result3 = max(2, 4, 7); //報(bào)錯(cuò)
let result4 = max(2, 7); //正常
2.3: 可選參數(shù)
在javascript里,被調(diào)用函數(shù)的每個(gè)函數(shù)都是可選的,而在typescript中,被調(diào)用的每個(gè)函數(shù)的每個(gè)參數(shù)都是必傳的。在編譯時(shí),會(huì)檢查函數(shù)每個(gè)參數(shù)是否傳值。簡(jiǎn)而言之,傳遞給一個(gè)函數(shù)的參數(shù)個(gè)數(shù)必須和函數(shù)定義的參數(shù)個(gè)數(shù)一致。但是實(shí)際開發(fā)中經(jīng)常需要根據(jù)實(shí)際需求來確認(rèn)參數(shù),這時(shí)可以添加?來定義可選參數(shù)。示例:
function max(x: number, y: number) {
if(y){
return x > y ? x : y;
} else {
return x
}
}
let result1 = max(2);
let result2 = max(2, 4, 7); //報(bào)錯(cuò)
let result3 = max(2, 4);
//注意:可選參數(shù)必須放在默認(rèn)參數(shù)后面
3:函數(shù)特性
3.1:剩余參數(shù)
上面介紹的必選參數(shù)、默認(rèn)參數(shù)以及可選參數(shù)共同點(diǎn)是只能表示某一個(gè)參數(shù)。當(dāng)需要同時(shí)操作多個(gè)參數(shù),或者并不知道會(huì)有多少參數(shù)傳遞進(jìn)來時(shí),就需要用到Typescript 里的剩余參數(shù)。示例:
function sum(x: number, ...restOfNumber: number[]){
let result = x;
restOfNumber.forEach(value => result += value);
return result;
}
let result1 = sum(1, 2, 3, 4, 5, 6);
console.log(result1);
let result2 = sum(2);
console.log(result2);
let result3 = sum(2, 5);
console.log(result3);
3.2: generator函數(shù)
控制函數(shù)的執(zhí)行過程,可以手動(dòng)的干預(yù)函數(shù)執(zhí)行。示例:
function getPrice(stock) {
while (1) {
yield Math.random() * 100;
}
}
var priceGenerator = getPrice('dcc');
var limitPrice = 51;
var price = 100;
while (price > limitPrice) {
price = priceGenerator.next().value;
console.log(`this generator return ${price}`);
}
console.log(`buying at ${price}`);
3.3: 析構(gòu)表達(dá)式
析構(gòu)表達(dá)式又稱解構(gòu),是ES6的一個(gè)重要特性,Typescript在1.5版本中開始增加了對(duì)結(jié)構(gòu)的支持,所謂結(jié)構(gòu),就是將聲明的一組變量與相同結(jié)構(gòu)的數(shù)組或者對(duì)象的元素?cái)?shù)值一一對(duì)應(yīng)。分?jǐn)?shù)組解構(gòu)([])和對(duì)象解構(gòu)({})兩種。
數(shù)組解構(gòu)示例:
let imput = [1, 2];
let [first, second] = input;
console.log(first); //相當(dāng)于inputp[0]
console.log(second); //相當(dāng)于input[1]
function f([first, second]) {
console.log(first + second)
}
f{[1, 3]} //結(jié)果是4
let [first, ...rest] = [1, 2, 3, 4];
console.log(first); //1
console.log(second); //[2,3,4]
對(duì)象解構(gòu)示例:
let test = {
x: 0,
y: 0,
width: 15,
heights: {
height1: 10,
height2: 20
}
};
let { x, y: myY, width, heights: {height2} } = test;
console.log(x, myY, width, height2); //輸出:0,10,15,20
4: 箭頭表達(dá)式
用來聲明匿名函數(shù),消除傳統(tǒng)匿名函數(shù)的this指針問題。示例:
function Test1(names: string) {
this.names = names;
setInterval(function() {
console.log('my name is ' + this.names);
}, 1000)
}
function Test2(names: string) {
this.names = names;
setInterval(() => {
console.log('my names is ' + this.names)
}, 1000)
}
var a = new Test1('daocheng'); //undefined
var b = new Test2('daocheng'); //daocheng
5: 循環(huán)
typescritpt中涉及三種高級(jí)循環(huán)方式:forEach()、for in、for of
forEach示例:
var myArray = [1, 2, 3, 4];
myArray.name = 'daocheng';
myArray.forEach(value => console.log(value)); //結(jié)果為1,2,3,4
//特點(diǎn):不支持break,會(huì)忽略(name)
for in 示例:
var myArray = [1, 2, 3, 4];
myArray.name = 'daocheng';
for (var n in myArray ) {
console.log(n)
} //結(jié)果為1,2,3,4
//特點(diǎn): 循環(huán)的結(jié)果是對(duì)象或者數(shù)組的鍵值。可以break
for of 示例:
var myArray = [1, 2, 3, 4];
myArray.name = 'daocheng';
for (var n of myArray) {
console.log(n)
} //結(jié)果是1,2,3,4
//特點(diǎn):忽略屬性,可以打斷。當(dāng)循環(huán)為字符串時(shí),會(huì)把字符串中每個(gè)字符打出來
6:類
傳統(tǒng)的JavaScript程序使用函數(shù)和基于原型(Prototype)繼承來創(chuàng)建可重用的“類”,這對(duì)于習(xí)慣了面向?qū)ο缶幊痰拈_發(fā)者來說不是很友好,Typescript中可以支持基于類(class)的面向?qū)ο缶幊?/p>
6.1: 類的聲明
class Car {
engine: string,
constructor(engine: string) {
this.engine = engine;
}
drive(distanceInMeters: number = 0) {
console.log(`aaa is running` + this.engine)
}
}
let car = new Car('petrol');
car.drive(100)
6.2: 類的封裝、繼承、多態(tài)
封裝、繼承、多態(tài)是面向?qū)ο蟮娜筇匦浴I厦娴睦影哑嚨男袨閷懙揭粋€(gè)類中,即所謂的封裝。在Typescript中,使用extends關(guān)鍵字可以方便的實(shí)現(xiàn).
繼承。示例:
class Car {
engine: string;
constructor(engine: string) {
this.engine = engine;
}
drive(distanceInMeter: number = 0){
console.log(`A car runs ${distanceInMeter}m
powered by` + this.engine)
}
}
class MotoCar extends Car {
constructor(engine: string) {
super(engine)
}
}
let tesla = new MotoCar('electricity');
tesla.drive();
//其中子類MotoCar的實(shí)例對(duì)象tesla調(diào)用了父類Car的drive()方法。
多態(tài)示例:
class Car {
engine: string;
constructor(engine: string) {
this.engine = engine;
}
drive(distanceInMeter: number = 0){
console.log(`A car runs ${distanceInMeter}m
powered by` + this.engine)
}
}
class Jeep extends Car {
constructor(engine: string) {
super(engine)
}
drive(distanceInMeters: number = 100) {
console.log('jeep...')
return super.drive(distanceInMeters);
}
}
let landRover: Car = new Jeep('petrol'); //實(shí)現(xiàn)多態(tài)
> Jeep子類中的drive()方法重寫了Car的drive()方法,這樣drive()方法在不同的類中就具有不同的功能,這就是多態(tài)。注意:子類和派生類的構(gòu)造函數(shù)中必須調(diào)用super(),它會(huì)實(shí)現(xiàn)父類構(gòu)造方法。
6.3: 修飾符
在類中的修飾符可以分為公共(public)、私有(private)、和受保護(hù)(protected)三種類型。在Typescript里,每個(gè)成員默認(rèn)為public,可以被自由的訪問。
私有修飾符示例:
class Car {
private engine: string;
constructor(engine: string) {
this.engine = engine;
}
}
new Car('petrol').engine; //報(bào)錯(cuò),私有屬性無法在類的外部訪問
受保護(hù)修飾符示例:
class Car {
engine: string;
constructor(engine: string) {
this.engine = engine;
}
protected drive() {
console.log('drving')
}
}
class MotoCar extends Car {
constructor(engine: string) {
super(engine)
}
moToDrive() {
super.drive()
}
}
let tesla = new MoToCar('electricity');
tesla.drive(); // 報(bào)錯(cuò),受保護(hù)成員只有子類訪問,實(shí)例對(duì)象不可
tesla,moToDrive()
6.4: 參數(shù)屬性
參數(shù)屬性是通過給構(gòu)造函數(shù)的參數(shù)添加一個(gè)訪問限定符來聲明。參數(shù)屬性可以方便地讓我們?cè)谝粋€(gè)地方定義并初始化類成員。我們來改造6.1中的例子:
class Car {
constructor(public engine: string) {}
drive() { }
}
6.5: 抽象類
Typescript有抽象類的概念,它是供其他類繼承的基類,不能直接被實(shí)例化。不同于接口,抽象類必須包含一些抽象方法,同時(shí)也可以包含非抽象的成員。抽象類中的抽象方法必須在派生類中實(shí)現(xiàn)。
abstract class Person {
abstract speak(): void;
walking(): void {
console.log('walking');
}
}
class Male extends Person {
speak(): void {
console.log('man wakling')
}
}
6.6: 接口
接口在面向?qū)ο笤O(shè)計(jì)中具有極其重要的作用,在Gof的23種設(shè)計(jì)模式中,基本上都可見到接口的身影。長(zhǎng)期以來,接口模式一直是Javascript這類弱類型語言的軟肋,Typescript接口的使用方式類似于Java。
在Typescript中接口有屬性類型、函數(shù)類型、可索引類型、類類型這幾種,在Angular的開發(fā)中主要使用類類型接口,我們使用interface關(guān)鍵字定義接口并用implements關(guān)鍵字實(shí)現(xiàn)接口。
類類型接口示例:
interfance Animal {
name: string;
setName();
}
class Dog implements Animal {
name: string;
setName() {
console.log(this.name)
}
constructor() { }
}
//接口更注重功能的設(shè)計(jì),抽象類更注重結(jié)構(gòu)內(nèi)容的體現(xiàn)
6.7: 模塊
ES6中引入了模塊的概念,在TypeScript中也支持模塊的使用。使用import和export關(guān)鍵字來建立兩個(gè)模塊之間的聯(lián)系。懂點(diǎn)node都知道模塊是什么了,不BB了。
7:裝飾器
裝飾器(Decorators)是一種特殊類型的聲明,它可以被附加到類聲明、方法、屬性或參數(shù)上。裝飾器有@符號(hào)緊接一個(gè)函數(shù)名稱,如:@expression,expression求職后必須是一個(gè)函數(shù),在函數(shù)執(zhí)行的時(shí)候裝飾器的聲明方法會(huì)被執(zhí)行。裝飾器是用來給附著的主題進(jìn)行裝飾,添加額外的行為。(裝飾器屬于ES7規(guī)范)
在Typescript的源碼中,官方提供了方法裝飾器、類裝飾器、參數(shù)裝飾器、屬性裝飾器等幾種每種裝飾器類型傳入的參數(shù)大不相同。這里我演示兩種裝飾器。
復(fù)合使用的例子:
function Component(component) {
console.log('selector: ' + component.selector);
console.log('template: ' + component.template);
console.log('component init');
return (target: any) => {
console.log('component call');
return target;
}
}
function Directive() {
console.log('directive init');
return (target: any) => {
console.log('directive call');
return target;
}
}
@Component({
selector: 'person',
template: 'person.html'
})
@Directive()
export class Person {}
let p = new Person();
//看不懂沒關(guān)系,知道有這么個(gè)東西就可以了,Angular框架在依賴注入、組件等部分中有多個(gè)復(fù)合裝飾器應(yīng)用的場(chǎng)景.畢竟裝飾器是ES7的草案標(biāo)準(zhǔn)。
8:泛型
參數(shù)化的類型,一般用來限制集合的內(nèi)容。
示例:
class MinHeap<T> {
list: T[] = [];
add(element: T): void {
//這里進(jìn)行大小比較,并將最小值放在數(shù)組頭部,功能代碼省略。
}
min(): T {
return this.list.length ? this.list[0] : null
}
}
let heap = new MinHeap<number>();
heap.add(3);
heap.add(5);
console.log(heap.min())
9:聲明文件
聲明文件也稱為類型定義文件,當(dāng)我們項(xiàng)目中要使用第三方的Javascript庫如jQuery、lodash等就需要用聲明文件,聲明文件是以.d.ts為后綴的形式存在的,其作用是描述一個(gè)Javascript模塊文件所有導(dǎo)出的接口類型信息。
例如使用jquery:
npm install –save @types/jquery