<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                [TOC] **編程思想:** 面向對象、面向過程、函數式編程 **面向對象是一種編程思想。(切入點)** **面向對象:** Oriented (基于) Object (事物) , 簡稱:OO 是一種編程思想,它提出一切以對象對切入點思考問題。 - JS沒有類型檢查,如果使用面向對象的方式開發,會產生大量的接口,這會導致調傭復雜度劇增。 所以必須通過嚴格的類型檢查來避免錯誤。盡管可以使用注解、文檔甚至是記憶力,但是它們沒有強約束力。 - TS帶來了完整的類型系統。在開發復雜項目時,都可以獲得完整的類型檢查。并且這種檢查是據有強約束力的。 對象繼承規則:子類成員不能改變父類成員的屬性類型 **設計模式:** 面對一些常見的功能場景,有一套固定、經過多年實踐、且非常成熟的方式處理這些問題,這種方法被稱之為設計模式。 ## :-: 抽象類 ``` // 模版模式:有些方法所有的子類實現的流程完全一致,只是流程中的某個步驟(規則)具體實現不一致。可以將該方法提取到父類,在父類中完成整個流程的實現。 // abstract -- 抽象類(對象不能單獨創建,只能被繼承) // 抽象類:只表示一個抽象概念,主要用于提取子類共有的成員,而不能直接創建它的對象。 abstract class A { // readonly -- 被修飾的字段為只讀類型,不可修改 // public -- 公開的(默認),所有代碼均可訪問。 // protected -- 受保護的成員,只能在自身和子類中訪問。 // private -- 私有的,只能在自身訪問,繼承的子類無法訪問。 protected a: number = 1; x: number = 0; y: number = 0; // abstract -- 抽象成員,必須出現在抽象類中。這些抽象成員必須在子類中實現。 // 父級中,可能知道有些成員是必須存在的,但是不知道該成員的值或實現是什么。因此需要強約束,讓繼承該類的子類必須實現這個成員(屬性/方法)。 abstract name: string; // 定義抽象成員 (子類必須實現) abstract rule(targetX: number, targetY: number): boolean; // 定義抽象方法 (子類必須實現這個方法) // 模版模式:有些方法所有的子類實現的流程完全一致,只是流程中的某個步驟(規則)具體實現不一致。 // 可以將該方法提取到父類,在父類中完成整個流程的實現。遇到實現不一致的方法時,將該方法做成抽象方法。 move(targetX: number, targetY: number): boolean { console.log("1.邊界判斷"); console.log("2.目標位置是否有乙方棋子"); // - 3.棋子移動規則判斷 if (this.rule(targetX, targetY)) { this.x=targetX; this.y=targetY; return true; } return false; } } class B extends A { // 假設rule是象棋的規則函數 rule(targetX: number, targetY: number): boolean { console.log("- 3.棋子移動規則判斷"); return true; } name = "馬"; // 父級定義了'抽象成員',子級必須要處理它,給予該屬性賦值。 e?: string = null; // super -- 讀取父類資源,調用父類的屬性/方法 // super.b } new B().move(5, 5); // const a = new A(); // 已經定義了抽象類,將無法創建抽象類的實例。 const b: A = new B(); // 鴨子辯型 if (b instanceof B) { // 觸發類型保護 b.e = undefined; } ``` ``` export interface IFireShow { name: string; } // 抽象類 export abstract class Animal {} // 子類 (必須實現IFireShow的接口) export class Lion extends Animal implements IFireShow { name = "xxx"; } // 類型保護函數:通過調用該函數,會觸發TS的類型保護,該函數必須返回 Boolean function hasShow(ani: object): ani is IFireShow { if ((ani as IFireShow).name) { return true; } return false; } // 接口可以繼承自類(class) // interface C extends Aobj,Bobj { } ``` ## :-: 靜態成員 ``` // 實例成員:屬于某個類的對象。'new User().log()' // 靜態成員(static):屬于某個類。'User.login()' class User { static Users: User[] = []; constructor(public name: string, public pwd: string) { User.Users.push(this); } // 定義靜態方法 static login(name: string, pwd: string): User | undefined { return User.Users.find(u => name === u.name && pwd === u.pwd); } log() { console.log(this.name, this.pwd); } } const u1 = new User("name_111", "pwd_111"); const u2 = new User("name_222", "pwd_222"); console.log(User.Users); console.log(User.login("name_111", "pwd_111")); ``` ## :-: 設計模式-單例模式 ``` // 所謂單例,就是整個程序有且僅有一個實例。該類負責創建自己的對象,同時確保只有一個對象被創建。 class Board { width: number = 500; height: number = 700; init() { console.log("初始化棋盤"); } private constructor() {} // 讓外部無法通過new的方式創建 private static _board?: Board; static createBoard(): Board { return this._board ? this._board : (this._board = new Board()); } } // new Board(); 此時構造函數是私有的,外部無法創建對象 Board.createBoard(); // 只會創建一次,無論被調用多少次都返回一樣的結果。 ``` ## :-: 索引器 ``` // 可以開啟'noImplicitAny'配置對隱式any進行檢查 class User1 { [prop: string]: string | boolean; // 對所有成員進行類型限制 name = "xxx"; } new User1()[0] = true; ``` ## :-: this指向約束 ``` // 使用bind、apply、call可以手動綁定this對象。 // 配置'noImplicitThis'為true,表示不允許this隱式的指向any interface u { name:string; age:number; sayHello(this:u): void; // 手動聲明該函數中this的指向。 } const user2:u = { name:"xxx", age:18, // sayHello(this:u) { ··· } sayHello() { console.log(this.name, this.age); } }; user2.sayHello(); // const fun=user2.sayHello;fun(); // 已經聲明約束了this指向,這種方式調用會報錯 ``` ## :-: 裝飾器 ### 概述 > - 面向對象的概念(java:注解、C#:特征),decorator > - 在`Angular`中大量使用,`React`中也有用到。 > - 目前 js 支持裝飾器,但是還沒有正式成為標準。(目前處于建議征集的第二階段) ### 解決的問題 > - 裝飾器,分離關注點。 > - 裝飾器的本質是一個函數,用于修飾 類、屬性、參數 ***** > `Object.getPrototypeOf(Obj).constructor.name` > 得到一個對象的原型 --> 構造函數 --> 定義的名 (User) ***** ### :-: 類裝飾器 ```ts // function test(target: Function) {} // 在ts中約束一個構造函數 Function | new()=>object function test(target: new (...args: any[]) => object) { // target -- 是類(A) new A(); } @test class A { ··· } ``` ### :-: 成員裝飾器 ```ts // 屬性 -- 屬性裝飾器也是一個函數,該函數提供兩個參數 // 1.如果是靜態屬性,則為類本身。如果是實例屬性,則為類的原型 // 2.固定為屬性名 // 方法 -- 方法裝飾器也是一個函數,該函數提供三個參數 // 1.如果是靜態屬性,則為類本身。如果是實例方法,則為類的原型 // 2.固定為屬性名 // 3.屬性描述對象 function enumerable(target: any, key: string, descriptor: PropertyDescriptor) { descriptor.enumerable = true; // 讓方法也可以被枚舉 } class B { @enumerable xxxxx() { /* ··· */ } } ``` ### :-: 推薦庫 - reflect-metadata -- 它專門用于維護類、屬性的元數據 ```ts import "reflect-metadata"; // 庫是全局的只需導入一次,不返回任何變量 const key = Symbol.for("descriptor"); // 絕對唯一 export function descriptor(description: string) { return Reflect.metadata(key, description); } export function printObj(obj: any) { const cons = Object.getPrototypeOf(obj); if (Reflect.hasMetadata(key, cons)) { console.log(Reflect.getMetadata(key, cons)); } else { console.log(cons.constructor.name); } // 輸出所有的屬性描述和屬性值 for (const k in obj) { if (Reflect.hasMetadata(key, obj, k)) { console.log(`\t${Reflect.getMetadata(key, obj, k)} : ${obj[k]}`); } else { console.log(`\t${k} : ${obj[k]}`); } } } // 第三方庫:reflect-metadata -- 它專門用于維護類、屬性的元數據 import { descriptor, printObj } from "./Descriptor"; @descriptor("文章") class Article { @descriptor("標題") title = "這是文章標題"; @descriptor("內容") content = "這是文章的內容"; @descriptor("時間") date = new Date(); } const article = new Article(); printObj(article); /* * Article * 標題 : 這是文章標題 * 內容 : 這是文章的內容 * 時間 : Sat Mar 28 2020 14:53:55 GMT+0800 (GMT+08:00) */ ``` - class-validator -- 屬性裝飾器,數據驗證 ```ts import { IsNotEmpty, validate, MinLength, MaxLength, Max, Min } from "class-validator"; import { Type } from "class-transformer"; class RegUser { @IsNotEmpty({ message: "帳號不能為空!" }) // 非空校驗 loginId!: string; @IsNotEmpty({ message: "密碼不能為空!" }) @MinLength(6, { message: "密碼不能小于6個字符!" }) @MaxLength(16, { message: "密碼不能大于16個字符!" }) loginPwd!: string; @Max(100, { message: "年齡必須小于100" }) @Min(0, { message: "年齡必須大于0" }) @Type(() => Number) // 一般用于將`axios`請求過來的數據中為string類型的字段,轉換為number類型。"123" -> 123 age!: number; gender!: "男" | "女"; } const post = new RegUser(); post.loginId = "id_xxx"; // post.loginPwd = "pwd_xxx"; post.age = -10; validate(post).then(errors => { // 驗證方法是異步執行的 console.log(errors); /* * [ * ValidationError { * target: RegUser { loginId: 'id_xxx', age: -10 }, -- 驗證哪個實例 * value: undefined, -- 賦的值是什么 * property: 'loginPwd', -- 屬性名 * children: [], * constraints: { -- 沒有實現的約束 * maxLength: '密碼不能大于16個字符!', * minLength: '密碼不能小于6個字符!', * isNotEmpty: '密碼不能為空!' * } * }, * ValidationError { * target: RegUser { loginId: 'id_xxx', age: -10 }, * value: -10, * property: 'age', * children: [], * constraints: { min: '年齡必須大于0' } * } * ] */ }); ``` - class-transformer -- 將平面對象轉換成類的對象。 ### 補充 - 參數裝飾器(依賴注入、依賴倒置) - 關于 ts 自動注入 - 面向對象 `AOP` ## :-: 類型演算 - `typeof` -- 當作用于類的時候,得到的類型,是該類的構造函數。 - `keyof` -- 作用于 類、接口、類型別名,用于獲取其他類型中的所有成員名組成的聯合類型。`const abc:keyof User;` - `in` -- 該關鍵字往往和 keyof 聯用,用于限制某個索引的取值范圍。 - `type UserString = { [key in 'loginId' | 'loginPwd' | 'age']:string }` - `type UserString = { [key in keyof User]:string }` - `type UserReadonly = { readonly [key in keyof User]?:User[key] }` - `type Partial<T> = { readonly [key in keyof T]?:T[key] }` -> `const u:Partial<User> = { ··· }` ### TS自帶的類型演算 ```ts Required<T> -- 將類型T中的成員變為必須 Readonly<T> -- 將類型T中的成員變為只讀 Exclude<T,U> -- 從T中移除可以賦值給U的類型 Extract<T,U> -- 相反,提取T中可以賦值給U的類型 NonNullable<T> -- 從T中移除 null 和 undefined ReturnType<T> -- 獲取函數返回值的類型 InstanceType<T> -- 獲取構造函數類型的實例類型 ``` ## :-: 聲明文件 ### 概述 - 創建一個以`.d.ts`結尾的文件 - 其作用是為普通的 js 代碼文件提供類型聲明 - 聲明文件的位置 - 放置到 `tsconfig.json` 配置中包含的目錄中 - 放置到 `node_modules/@types` 文件夾中 - 手動配置 - 與 js 代碼所在的目錄相同,并且文件名也相同的文件,用 ts 代碼書寫的工程發布之后的格式,(推薦) ### 編寫 - 手動編寫 - 自動生成 -- 工程是使用 ts 開發的,配置`declaration`為`true`即可。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看