1.TypeScript概述
1.1始於JavaScript,歸於JavaScript
TypeScript從今天數以百萬計的JavaScript開發者所熟悉的語法和語義開始。使用現有的JavaScript代碼,包括流行的JavaScript庫,並從JavaScript代碼中調用TypeScript代碼。
TypeScript可以編譯出純淨、 簡潔的JavaScript代碼,並且可以運行在任何瀏覽器上、Node.js環境中和任何支持ECMAScript 3(或更高版本)的JavaScript引擎中。
1.2強大的工具構建 大型應用程序
類型允許JavaScript開發者在開發JavaScript應用程序時使用高效的開發工具和常用操作比如靜態檢查和代碼重構。
類型是可選的,類型推斷讓一些類型的註釋使你的代碼的靜態驗證有很大的不同。類型讓你定義軟件組件之間的接口和洞察現有JavaScript庫的行爲。
1.3先進的 JavaScript
TypeScript提供最新的和不斷髮展的JavaScript特性,包括那些來自2015年的ECMAScript和未來的提案中的特性,比如異步功能和Decorators,以幫助建立健壯的組件。
這些特性爲高可信應用程序開發時是可用的,但是會被編譯成簡潔的ECMAScript3(或更新版本)的JavaScript。
2.字符串新特性
2.1多行字符串
不需要使用+號拼接字符串,可讀性強,寫法簡單。 `號在tab鍵上面。
let content = `aaa
bbb
ccc`;
2.2字符串模板
將變量name使用${name}拼接到字符串中。
let name = 'zhiyu';
let getName = () => {
return 'z哥';
}
console.log(`my name is ${name}`); // my name is zhiyu
console.log(`my name is ${getName()}`);// my name is z哥
2.3自動拆分字符串
將字符串中模板變量和非模板變量自動拆分。
let name = 'zhiyu';
let getAge = () => {
return 24;
}
function test(template, name, age) {
console.log(template);
console.log(name);
console.log(age);
}
test`我是${name},我${getAge()}歲`; // ["我是", ",我", "歲"] zhiyu 24
3.參數新特性
3.1參數類型
在參數後面使用冒號來指定參數的類型
let myName: string = 'zhiyu';
myName = 18; // 錯誤 Type '18' is not assignable to type 'string'.
let allType: any = 'haha'; // any類型可以賦值任何類型
allType = 12;
allType = true;
let age: number = 24; // number類型
let man: boolean = true; // boolean類型
// void不需要任何返回值
function testVoid(): void {
return ''; // 錯誤 Type '""' is not assignable to type 'void'.
}
//返回string類型的值
function testString(): string {
return '';
}
//傳入的參數age必須爲number,返回number
function getAge(age: number): number {
return age + 1;
}
getAge(23);
getAge('23'); // 錯誤 Argument of type '"23"' is not assignable to parameter of type 'number'.
// 自定義Person類型
class Person{
name:string;
age:number;
}
let zhiyu:Person = new Person();
zhiyu.name = 'zhiyu';
zhiyu.age = 24;
3.2參數默認值
在參數後面使用等號來指定參數的默認值
function test(a: string, b: string, c: string) {
console.log(a);
console.log(b);
console.log(c);
}
test('xxx','yyy','zzz'); // 'xxx' 'yyy' 'zzz'
// 參數設置默認值應該寫在最後,c的默認值是zhiyu,調用test2時不傳c參數,則c是zhiyu
function test2(a: string, b: string, c: string = 'zhiyu') {
console.log(a);
console.log(b);
console.log(c);
}
test2('xxx','yyy'); // 'xxx' 'yyy' 'zhiyu'
test2('xxx','yyy','uuu'); // 'xxx' 'yyy' 'uuu'
3.3參數默認值
在方法的參數聲明後面使用問號來表明參數爲可選參數
// 可選參數應該聲明的必選參數後面,需要在方法裏面處理不傳可選參數時的情況
function test(a: string, b?: string, c: string = 'zhiyu') {
console.log(a);
b ? console.log(b) : () => { };
console.log(c);
}
test('xxx'); // 'xxx' 'zhiyu'
4.函數新特性
4.1Rest and Spread 操作符
用來聲明任意數量的方法參數
function test(...args) {
args.forEach((arg) => {
console.log(arg);
})
}
test(1, 2); // 1 2
test(4, 5, 6, 7, 8, 9, 10); // 4 5 6 7 8 9 10
function test2(a: number, b: number, c: number) {
console.log(a);
console.log(b);
console.log(c);
}
let args = [1, 2];
let args2 = [4,5,6,7];
// 將任意數量的參數變爲固定數量的參數
// 該寫法在ts中暫時不支持,但是編譯出來的js可以實現功能
test2(...args); // 1 2 undefined
test2(...args2); // 4 5 6
4.2 generator函數
控制函數的執行過程,手工暫停和恢復代碼執行
function* doSomething() {
console.log('start');
yield;
console.log('middle');
yield;
console.log('end');
}
// 定義一個變量func1
let func1 = doSomething();
func1.next(); // start
func1.next(); // middle
func1.next(); // end
// 當股票價格低於15元時購買該股票
function* getStockPrice(stock: string) {
while (true) {
yield Math.random() * 100;
}
}
let getStock = getStockPrice('IBM');
let limitPrice = 15;
let price = 100;
while (price > limitPrice) {
price = getStock.next().value;
console.log(`current prcie is ${price}`);
}
console.log(`buying at ${price}`);
// current prcie is 76.11991753923921
// current prcie is 6.342549180037449
// buying at 6.342549180037449
4.3 destructuring析構表達式
通過表達式將對象或數組拆解成任意數量的變量
對象析構表達式
function getInfo() {
return {
myAge: 24,
myName: 'zhiyu'
}
}
let { myAge, myName } = getInfo();
console.log(myAge); // 24
console.log(myName); // zhiyu
// myAgeTemp myNameTemp 爲別名
let { myAge: myAgeTemp, myName: myNameTemp } = getInfo();
console.log(myAgeTemp); // 24
console.log(myNameTemp); // zhiyu
function getInfo2() {
return {
myAge2: 24,
myName2: {
name1: 'zhiyu',
name2: 'z哥'
}
}
}
let { myAge2, myName2 } = getInfo2();
console.log(myAge2); // 24
console.log(myName2); // {name1: "zhiyu", name2: "z哥"}
// myName2後再寫一個析構表達式,可以獲取name2的值
let { myAge2: myAge2temp, myName2: { name2 } } = getInfo2();
console.log(myAge2temp); // 24
console.log(name2); // z哥
數組的析構表達式
let array = [1, 2, 3, 4];
let [number1, number2] = array;
console.log(number1); // 1
console.log(number2); // 2
let [num1, , , num2] = array;
console.log(num1); // 1
console.log(num2); // 4
let [, , num3, num4] = array;
console.log(num3); // 3
console.log(num4); // 4
let [no1, no2, ...others] = array;
console.log(no1); // 1
console.log(no2); // 4
console.log(others); // [3, 4]
function test([no1, no2, ...others]) {
console.log(no1); // 1
console.log(no2); // 4
console.log(others); // [3, 4]
}
test(array);
5.表達式與循環
5.1箭頭表達式
用來聲明匿名函數,消除傳統匿名函數的this指針問題
function getName(name:string){
this.name = name;
setTimeout(function(){
console.log('name is ' + this.name)
},1000);
}
var getName2Temp = new getName('zhiyu'); // name is ,此時this指向Window
function getName2(name:string){
this.name = name;
setTimeout(() =>{
console.log('name is ' + this.name)
},1000);
}
var getName2Temp = new getName2('z哥'); // name is z哥
let array1 = [1,2,3,4];
console.log(array1.filter(value => value%2 === 0)); // [2, 4]
5.2forEach for in for of 循環
let array = [1, 2, 3, 4];
array['desc'] = 'four numbers';
array.forEach(value => console.log(value)); // 1 2 3 4
for (let i in array) {
console.log(i); // 0 1 2 3 desc
}
for (let i in array) {
console.log(array[i]); // 1 2 3 4 four numbers
}
for (let j of array) {
console.log(j); // 1 2 3 4
}
for (let j of 'four') {
console.log(j); // 'f' 'o' 'u' 'r'
}
6.class
6.1 定義一個類,並實例化
class Person {
name;
eat() {
console.log(this.name);
}
}
let p1 = new Person();
p1.name = 'zhiyu';
p1.eat(); // zhiyu
let p2 = new Person();
p2.name = 'z哥';
p2.eat(); // z哥
6.2 構造函數
class Person {
// 在constructor聲明屬性的時候必須指定修飾符public private protected其中之一
constructor(public name: string) {
}
eat() {
console.log(this.name);
}
}
// 實例化必須指定name
let p1 = new Person('zhiyu');
p1.eat(); // zhiyu
let p2 = new Person('z哥');
p2.eat(); // z哥
6.3 extends關鍵字
class Person {
// 在constructor聲明屬性的時候必須指定修飾符public private protected其中之一
constructor(public name: string) {
}
eat() {
console.log(this.name);
}
}
class Employee extends Person {
code: string;
work() {
console.log(this.code + ' is working');
}
}
let e1 = new Employee('zzz');
e1.code = '123';
e1.work(); // 123 is working
6.4 super關鍵字
class Person {
// 在constructor聲明屬性的時候必須指定修飾符public private protected其中之一
constructor(public name: string) {
}
eat() {
console.log('eating');
}
}
class Employee extends Person {
constructor(name: string, code: string) {
super(name);
this.code = code;
}
code: string;
work() {
super.eat();
this.doWork();
}
private doWork() {
console.log('working');
}
}
let e1 = new Employee('zzz', '111');
e1.work(); // eating working
7.泛型
參數化的類型,一般用來限制集合的內容
class Person {
// 在constructor聲明屬性的時候必須指定修飾符public private protected其中之一
constructor(public name: string) {
}
eat() {
console.log('eating');
}
}
class Employee extends Person {
constructor(name: string, code: string) {
super(name);
this.code = code;
}
code: string;
work() {
super.eat();
this.doWork();
}
private doWork() {
console.log('working');
}
}
// 指定數組元素爲Person類
let workers: Array<Person> = [];
workers[0] = new Person('z');
// Employee繼承Person類,是Person類的子類
workers[1] = new Employee('zzz', '111');
workers[1] = 1; // 錯誤 Type '1' is not assignable to type 'Person'.
8.interface
接口用來建立某種代碼約定,使其他開發者在調用某個方法或者創建新的類的時候必須遵循接口所定義的代碼約定。
8.1限制傳入參數必須爲某種類型
interface IPerson {
name: string;
age: number;
}
class Person {
constructor(public config: IPerson) {
}
}
let p1 = new Person({
name: 'zhiyu',
age: 24
})
8.2 implements關鍵字實現interface
interface Animal {
eat();
}
// 必須實現eat(),否則報錯
class Sheep implements Animal {
eat() {
console.log('I eat grass');
}
}
class Tiger implements Animal {
eat() {
console.log('I eat meat');
}
}
9.module
模塊可以幫助開發者將代碼分割爲可重用的單元。開發者可以決定將模塊中哪些資源(類,方法,變量)暴露出去供外部使用,哪些資源僅供內部使用。
// a.ts
export let prop1;
let prop2;
export class Clazz1 {
}
class Clazz2 {
}
export function func1() {
}
function func2() {
}
// b.ts
import { prop1, func1, Clazz1 } from './a'
console.log(prop1);
func1();
new Clazz1()