typescript從入門到現在的總結 1

前段時間發表了node的學習
現在丸子終於要對ts進行總結跟回顧了
目錄

  1. 函數
  2. 類型約束
  3. 函數重載
  4. this問題
  5. .靜態成員
  6. 繼承
  7. 抽象類
  8. 接口基礎
  9. 接口可選結構
  10. 接口檢測約束
  11. 接口索引簽名
  12. 接口函數類型接口
  13. 類接口
  14. 案例
/**
 * 函數
 *      函數聲明
 *      函數表達式
 * 
 * 類型約束
 *      函數參數
 *      函數返回值
 * 
 * 如果函數沒有返回值,使用 void,不是undefined
 * // function fn1(x: number, y: number): number {
//     return x + y;
// }

// fn1(1,2);
// fn1('a', 'b');



// 函數表達式
// let fn2 = function(x: number, y: number): number {
//     return x + y;
// }

// let a: number = 1;

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

// 根據類型推斷可以簡寫
// let fn2: (x: number, y: number) => number = function(x, y) {
//     return x + y;
// }

// fn2('a', 'b');
// fn2('a', 'b');
// fn2(1, 2);





// 可選參數
// function fn3(x: number, y?: number): void {}
// fn3(1);





// 參數默認值
// function fn3(x: number, y = 1): void {
//     console.log(y);
// }
// fn3(0);




// 剩餘參數
// function fn4(...args: any[]) {
//     console.log(args);
// }
 */
 

2.函數重載

// 如果是在js中
// function fn(x, y) {
//     return x + y;
// }

// fn(1, 2);
// fn('a', 'b');


// 函數重載
// function fn(x: number, y: number): number;
// function fn(x: string, y: string): string;

// function fn(x: any, y: any): any {
//     return x + y;
// }

// fn(1, 2);
// fn('a', 'b');
// fn(1, 'a');

ts裏面的this

/**
 * ts中默認情況下函數中的this默認指向 : any
 */

let obj = {
    a: 10,
    fn() {
        // 因爲默認情況下,this是any類型,any類型ts不能提示有任何屬性方法
        // let document:any;
        // any的值,ts不能提示或者進行類型屬性檢測
        // console.log(this.b);

        // 使用noImplicitThis選項可以取消默認this的any來這個設置
        // this.a
    }
}

// obj.fn();


// ts會自動推導事件函數中的this
// document.onclick = function() {
//     this
// }


let obj1 = {
    a: 1,
    fn(this: Element|Document) {    // 在ts中函數的第一個this參數是用來設置this類型約束的
        // 這個this是一個假參數,運行過程中是不存在,是給ts檢測使用的
        // console.log(this);
        // 希望ts是按照事件函數中的this去做檢測
        this;   //檢測檢測檢測

        // this
    }
};

document.onclick = obj1.fn;
document.body.onclick = obj1.fn;

// function fn10(x: number) {

// }

// fn10( document.querySelector('input').value );

ts中的類

// class Person {
//     /**
//      * ts中的類,成員屬性必須要聲明後使用
//      * ts中類的成員屬性不是在構造函數中聲明的,是在class內,方法外
//      * 
//      * public
//      *      公開的,所有的地方都能訪問,屬性和方法默認是public
//      * protected
//      *      受保護的,在類的內部和他的子類中才能訪問
//      * private
//      *      私有的,只能在該對象(類)的內部纔可以訪問
//      */

//     public username: string = '';
//     // private username: string = '';
//     // protected username: string = '';

//     // readonly username: string = '';

//     constructor(name: string) {
//         this.username = name;
//     }

// }

// class Student extends Person {

//     say() {
//         this.username
//     }
// }

// let p1: Person = new Person('Kimoo');

// p1.username = 'zmouse';


class Person {

    username: string = 'Kimoo';
    // private age: number = 10;

    private _age: number = 10;

    // getAge(): number {
    //     return this.age;
    // }

    // setAge(age: number): void {
    //     if (age > 0 && age < 150) {
    //         this.age = age;
    //     }
    // }

    // 存取器,這個a並不會作爲方法,而是屬性去訪問
    get age(): number {
        return this._age;
    }

    set age(age: number) {
        if (age > 0 && age < 150) {
            this._age = age;
        }
    }

}

let p1: Person = new Person();

/**
 * 允許在外部獲取和修改age的值,但是不希望該修改成非法的,比如1000歲
 */
// p1.age = 1100;

// console.log(p1);

// p1.setAge(20);
// p1.setAge(200);
// console.log(p1.getAge());

// console.log( p1.a );

/**
 * 單例
 */

// class Mysql {

//     host: string;
//     port: number;
//     username: string;
//     password: string;
//     dbname: string;

//     constructor(host = '127.0.0.1', port = 3306, username='root', password='', dbname='') {
//         this.host = host;
//         this.port = port;
//         this.username = username;
//         this.password = password;
//         this.dbname = dbname;
//     }

//     query() {}
//     insert() {}
//     update() {}

// }

/**
 * 創建一個Mysql對象,通過這個對象來操作數據庫
 * 如果我們不加以限制的話,這個Mysql是可以new出來多個對象的
 * 每一個Mysql都會佔用資源(內存)
 */
// let db = new Mysql();
// db.query();
// db.insert();

// let db1 = new Mysql();
// db1.query();
// db1.insert();




/**
 * 通過某種方法控制系統同時只有一個Mysql的對象在工作
 * 通過口頭去約定是不靠譜的
 */

class Mysql {

    // 靜態屬性,不需要通過new出來的對象方面,直接是通過Mysql類來訪問
    public static instance;

    host: string;
    port: number;
    username: string;
    password: string;
    dbname: string;

    private constructor(host = '127.0.0.1', port = 3306, username='root', password='', dbname='') {
        this.host = host;
        this.port = port;
        this.username = username;
        this.password = password;
        this.dbname = dbname;
    }

    public static getInstance() {
        if (!Mysql.instance) {
            Mysql.instance = new Mysql();
        }
        return Mysql.instance;
    }

    query() {}
    insert() {}
    update() {}

}


// let db = new Mysql();

// console.log(Mysql.instance);

let db = Mysql.getInstance();
db.query();
db.insert();

4.繼承

class Person {

    private _a = 1;

    // 在構造函數的參數中如果直接使用public等修飾符,則等同於同時創建了該屬性
    constructor(public username: string, public age: number) {
        this.username = username;
        this.age = age;
    }

}

class Student extends Person {

    // 如果子類沒有重寫構造函數,則直接父類的
    // 如果子類重寫了構造函數
    // 注意:需要手動調用父類構造函數
    // super:關鍵字,表示父類
    constructor(username: string, age: number, public type: string) {
        super(username, age);    //執行父類構造函數

        this.type = type;
    }

}

let s1 = new Student('Kimoo', 30, 'javascript');

5.抽象類

abstract class Person { //抽象類不能實例化的
    username: string;

    constructor(username: string) {
        this.username = username;
    }

    say() {
        console.log('哈哈哈哈哈');
    }

    // 雖然子類都會有這樣的特性,學習,但是子類學習具體過程不一 樣,所在在父類確定
    // 不了study方法的具體實現,父類只能有抽象約定,接收什麼參數,返回什麼內容
    // 如果一個類中有抽象的方法了,那麼這個類也必須是抽象的
    abstract study(): void   //抽象方面是沒有具體代碼的
}


class Student extends Person {

    study() {
        console.log('學生有學生的學習方法 - 需要老師教授');
    }

}

class Teacher extends Person {

    study() {
        console.log('自學');
    }

}

// 如果一個類繼承了抽象的父類,就必須實現所有抽象方面,否則這個子類還是必須得爲抽象的
// abstract class P extends Person {

// }


// new Person();

interface

// /**
//  * interface
//  *      爲我們提供一種方式來定義某種結構,ts按照這種結構來檢測數據
//  * 
//  *      寫法
//  *          interface 接口名稱 {
//  *              // ... 接口規則
//  *          }
//  * 
//  *  接口中定義的規則只有抽象描述,不能有具體的值與實現的
//  * 
//  *  對象抽象 => 類(對象的抽象描述)
//  *  類抽象 => 抽象類(如果一個類中擁有一個沒有具體實現的抽象方法,就是抽象類)
//  *  抽象類 => 接口(如果一個抽象類的成員全部是抽象的,那麼可以看做接口)
//  */

// interface Options {
//     width: number,
//     height: number
// }

// function fn(opts: Options) {}

// // 類型檢測只檢測必須的屬性是否存在,不會按照順序進行,無序的
// fn({
//     height: 200,
//     width: 100
// });

可選結構

// /**
//  * 如果規則中有些是可選的,那麼通過 ? 標識
//  */

// interface Options {
//     width: number,
//     height: number,
//     color?: string
// }

// function fn(opts: Options) {}

// fn({
//     height: 200,
//     width: 100
// });

檢測約束

// /**
//  * 如果我們希望檢測不必要這麼複雜
//  *      - 如果我們希望某些時候,只要包含其中一些規則即可
//  *          - 通過可選 ? 來實現
//  *          - 通過 as 斷言
//  *          - 通過變量轉換
//  */

// interface Options {
//     width: number,
//     height: number,
//     color: string
// }

// function fn(opts: Options) {}

// // 告知ts檢測,我傳入的就是一個Options
// // fn({
// //     height: 200,
// //     width: 100
// // } as Options);

// // 先賦值給一個變量,也可以繞開 檢測
// // let obj = {
// //     height: 200,
// //     width: 100,
// //     color: 'red',
// //     a: 1
// // }
// // fn( obj );

索引簽名

// /**
//  * 希望規則是:一組由數字進行key命名的對象
//  * 我們可以使用索引簽名
//  *  爲數據定義一組具有某種特性的key的數據
//  *  索引key的類型只能是 number 和 string 兩種
//  */

// // interface Options {
// //     // key 是number,value是any類型的數據
// //     [attr: number]: any,
// //     length: number
// // }

// // function fn(opt: Options) {}

// // fn({
// //     0: 100,
// //     1: 100,
// //     2: 2000,
// //     length: 1
// // });



// interface Options {
//     // 索引簽名的key課是number,也可以是string
//     [attr: string]: any,
//     length: number
// }

// function fn(opt: Options) {}

// fn({
//     a: 1,
//     b: 2,
//     length: 100
// });

函數類型接口

/**
 * 這個接口描述的是一個包含有fn並且值的類型爲函數的結構體,並不是描述函數結構
 * 而是一個包含函數的對象結構
 */
// interface Options {
//     fn: Function
// }

// let o: Options = {
//     fn: function() {}
// }
// let fn: (x: number, y: number) => number = function(x: number, y: number): number {return x + y}


/**
 * 定義一個事件函數,那麼這個函數必須得有一定的規則了
 * 我們不能隨便的把一個函數賦值給事件
 */
// function fn(x: MouseEvent) {
//     console.log(x.clientX);
// }

// document.onkeydown = fn;


// 我們也可以使用 interface 來約定定義函數的結構

// 定義的是函數接口
// interface IFn {
//     (x: number, y: number): number
// }


// let fn: IFn = function(x: number, y: number): number {return x + y}


// 定義了一個接受一個MouseEvent類型參數的函數結構
// interface MouseEventCallBack {
//     (e: MouseEvent): any
// }

// let fn: MouseEventCallBack = function(a: MouseEvent) {

// }

// document.onclick = fn;


// interface ResponseCallBack {
//     (rs: Response): any
// }

// function todo(callback: ResponseCallBack) {
//     callback(new Response);
// }


// todo(function(x: string) {

// });

// fetch('url').then( (a: Response) => {
//     a.json();
// } );


// interface AjaxData {
//     code: number;
//     data: any
// }
// interface AjaxCallback {
//     (rs: AjaxData): any
// }


// function ajax(callback: AjaxCallback) {
//     callback({
//         code: 1,
//         data: []
//     });
// }


// ajax( function(x: AjaxData) {
//     x.code
//     x.data

//     x.message
// } );


類接口

/**
 * 類接口
 *      使用接口讓某個類去符合某種契約
 * 
 * 類可以通過 implements 關鍵字去實現某個接口
 *      - implements 某個接口的類必須實現這個接口中確定所有的內容
 *      - 一個類只能有一個父類,但是可以implements多個接口,多個接口使用逗號分隔
 */
 /**
 * 類接口
 *      使用接口讓某個類去符合某種契約
 * 
 * 類可以通過 implements 關鍵字去實現某個接口
 *      - implements 某個接口的類必須實現這個接口中確定所有的內容
 *      - 一個類只能有一個父類,但是可以implements多個接口,多個接口使用逗號分隔
 */

interface ISuper {
    fly(): void;
}

class Man {

    constructor(public name: string) {
    }

}

class SuperMan extends Man implements ISuper {

    fly() {
        console.log('起飛');
    }

}

class Cat {

}

class SuperCat extends Cat implements ISuper {
    fly() {
        console.log('起飛');
    }
}

let kimoo = new SuperMan('Kimoo');

案例

js的案例如下
function http(options) {

    let options = Object.assign({
        method: 'get',
        url: '',
        isAsync: true
    }, options);

    return new Promise((resolve, reject) => {
        let xhr = new XMLHttpRequest();
        xhr.open(options.method, options.url, options.isAsync);

        xhr.onload = function() {
            resolve( JSON.parse(xhr.responseText) );
        }

        xhr.onerror = function() {
            reject({
                code: xhr.response.code,
                message: '出錯了'
            });
        }

        xhr.send();
    })
}

http()

http({
    methods: 'get',
    url: '....',
    isAsync: true
});

http({
    methods: 'post',
    url: '....',
    isAsync: true
});

換成ts的寫法
interface HttpOptions {
    method: string,
    url: string,
    isAsync: true
}
interface HttpResponseData {
    code: number,
    data: any
}

function http(options: HttpOptions) {

    let opt:HttpOptions = Object.assign({
        method: 'get',
        url: '',
        isAsync: true
    }, options);

    return new Promise((resolve, reject) => {
        let xhr = new XMLHttpRequest();
        xhr.open(opt.method, opt.url, opt.isAsync);

        xhr.onload = function() {
            let data: HttpResponseData = JSON.parse(xhr.responseText);
            resolve( data );
        }

        xhr.onerror = function() {
            reject({
                code: xhr.response.code,
                message: '出錯了'
            });
        }

        xhr.send();
    })
}


http({
    method: 'get',
    url: '....',
    isAsync: true
}).then( (rs: HttpResponseData) => {
    rs.code
} );


// @Controller
// class IndexController {

    
//     index() {

//     }

//     @router('/')
//     @method('get')
//     main() {

//     }

// }



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章