關於學習TS中的一些筆記

前段時間學習了ts,做了一些筆記,想着還是發到博客上來!

console.log('你好呀!TS')
function getData() {
} 
let str: string = '你好TS'
console.log(str)
let arr:number[] = [1,2,3];
console.log(arr);
let arr2:Array<string> = ['1', '2', '3'];
console.log(arr2)
// 元組類型 給數組中某個元素指定指定的類型
let arr:[number, string] =
[1,'456'] console.log(arr)

1. 枚舉類型

enum Flag {
success = 1,
error = 0
};
let s: Flag = Flag.success;
console.log(s) //打印出1
enum Color {blue,red,yellow,black};
let c: Color = Color.yellow;
console.log(c) // 2如果標識符沒有賦值,它的值對應的就是下標

2. 任意類型 any; 空類型:null; undefined void:啥也不是

3. never類型:是其他類型(包括null和undefined)的子類型,代表從不會出現的值

定義函數的方法,在函數傳參的時候指定類型和
輸出指定類型;1.可選參數age?:number;可選參數age: number=20;


function func1(name: string, age:number):number {
  return 123
} 
const func2 = function():string {
  return '123'
}

若沒有返回值:

function func3(name: string, age: number): void {
  console.log('這是一個沒有返回值的函數')
} 

函數的重載,同名的函數傳入不同的參數得到不同的結果es5中出現同名方法,下面的會替代上面的方法;但是在TS中允許同名函數.
ts中的重載:

function getInfo(name: string): string;

function getInfo(age: number): number;

function getInfo(str:any):any {
  if(typeof str==='string'){
    return '名字:'+str
  }else {
    return '年齡:'+123 //返回一個數
  }
} 
getInfo('zhangsan')

es5中的繼承,冒充(Person.call(this)):無法繼承原型鏈原型鏈繼承 Work.prototype = new Person():實例化的時候沒法給父類傳參;

在TS中定義類:
class Person {
  name: string; // 屬性 前面省略了public關鍵字
  constructor(n: string) { //實例化的時候觸發的方法
    this.name = n;
  };
  run():void {
   console.log(this.name)
  }
} 
const P = new Person('zhangsan')
P.run()
// 在TS中實現繼承(super,extends: 繼承)
class Person {
  name: string;
  constructor(name:string) {
    this.name = name;
  };
  run():string {
   console.log(this.name)
  }
} 
class Web extends Person {
  constructor(name: string){
    super(name);
  }
} 
const w = new Web('lisi')
w.run();

類裏面的修飾符:
1. public:共有;
2. protected:受保護類型,在類裏面,子類裏面可以訪問,在類外部無法訪問;
3. private:在類裏面可以訪問,在子類和類外部五方訪問
4. 屬性不加修飾符,默認是public屬性,表示共有屬性

TS如何定義靜態方法

class Person {
  public name:string;
  constructor(name:string) {
    this.name = name;
  }
  run() {
    console.log('asdfds')
  }
  static work() { //靜態沒辦法調用類裏面的方法和屬性
    console.log('renshengyijingrucidejiannan')
  }
} 

// Person.work()// 調用靜態方法

多態:父類定義一個方法不去實現,讓繼承它的子類去實現,每一個子類有不同的表現抽象類,抽象方法使用關鍵字,抽象類的子類必須實現抽象類裏面的抽象方法。

abstract class Animal {
  name:string;
  constructor(name:any){
    this.name = name;
  }
  abstract eat():any;
} 

class Dog extends Animal {
  constructor(name: any) {
    super(name);
  };
  eat() {
    console.log(this.name + '抽象方法繼承')
  }
} 
const dog = new Dog('小花花')

TS中的接口(interface):接口是一種規範的定義,可以規範屬性,函數,類等

1. 屬性接口,對json的約束

interface FullName {
  firstName: string;
  lastName: string;
  age?:number; //可選屬性
} 
function printName(name: FullName) {
  return (name.firstName+'--'+name.lastName+'年齡:'+name.age)
} 
const obj = {
  firstName:'zhang',
  lastName:'san',
  age: 18
} 
let str = printName(obj);
console.log(str)

2. 函數類型接口

interface encrypt {
  (key:string, value:string):string;
} 

const md5: encrypt = function(key:string,value: string):string {
  return key+value;
} 

console.log(md5('name','zhangsan'))

function createArray(length: number, value:any): Array<any> {
  let result = [];
  for (let i = 0; i < length; i++) {
    result[i] = value++;
  } 

  return result;
} 

createArray(3, x); // ['x', 'x', 'x']

3. 可索引接口:針對數組,對象的約束(不常用)
4. 類--類型接口:對類的約束和抽象類有點相似(使用implements實現接口)類繼承接口

interface Animal {
  name: string;
  eat(str: string):void;
}

class Dog implements Animal {
  name: string;
  constructor(name:string){
    this.name = name
  };
  eat() {
    console.log(this.name + '吃骨頭')
  }
}

const d = new Dog('小黑')
d.eat()

5. 接口的擴展:接口可以繼承接口(切記只有類型可以實現接口(反之不行),接口可以通過extends繼承接口,接口不能繼承類!!!!

interface Animal {
  eat():void;
}
interface People extends Animal {// 這裏的人接口就繼承了Animal接口
  work(): void;
} 

class Programmer {
  name: string;
  constructor(name: string) {
    this.name = name;
  };
  coding(code: string) {
    console.log(this.name + code)
  }
} 
class Web extends Programmer implements People { //被當做類來處理
  constructor(name: string) {
    super(name) /**這裏繼承了類,必須要有super*/
  };
  eat(){
    console.log(this.name + '喜歡吃肉')
  };
  work(){
    console.log('前端工程師')
  }
}

const W = new Web('zhanghu');
W.eat();
W.work();
W.coding('寫代碼')

泛型: 使用泛型來創建可重用的組件;要求傳入參數和返回的類型一致

示例

function identify<T>(arg: T): T {
  return arg;
} 

let output = identify<string>('人生就像一場戲');
console.log(output); 

// 創建自定義泛型Array
function loggingIdentity<T>(arg: Array<T>):Array<T> {
  console.log(arg.length);
  return arg
} 

let arr = loggingIdentity([1,2,3,4])
console.log(arr)

function identify<T>(arg:T):T{
  return arg;
}

* 以下三種表達式同樣的效果喲
* 以下三種表達式同樣的效果喲

let myIdentify:<T>(arg: T) => T = identify;
let myIdentity: {<T>(arg: T): T} = identity;// 對象字面量來定義
let myIdentity: <U>(arg: U) => U = identity;


把上面的對象字面量來作爲一個接口
interface GenericIdentify {
  <T>(arg: T): T;
} 
function identify<T>(arg:T):T{
  return arg;
} 
let myIdentify: GenericIdentify = identify;

泛型接口

interface GenericIdentify<T> {
  (arg: T): T; //說明接口裏面是一個函數
} 

function identify<T>(arg: T): T {
  return arg;
} 

let myIdentify: GenericIdentify<string> =identify;

myIdentify('zhanghu')

泛型類

class Minclass {
  public list: number[] = [7,77,88];
  add(num: number) {
    this.list.push(num);
  };
  min():number {
    return Math.min(...this.list)
  }
} 

let m = new Minclass();
m.add(26);
m.add(46);
m.add(12);
m.add(8);

console.log(m.list)
console.log(m.min())
class Minclass<T> { //這裏聲明它是一個泛型類
  public list: T[] = [];
  add(value: T):void {
    this.list.push(value);
  };
  min():T {
  let minNUm = this.list[0];
  for(let i=0;i<this.list.length;i++) {
    if(minNUm>this.list[i]) {
      minNUm = this.list[i]
    }
  } 

  return minNUm
  }
} 

let Min = new Minclass<string>();//實例化類,並且制定了類的T代表的類型是number
// Min.add('123') //錯誤的寫法
Min.add('456');
Min.add('45');
Min.add('46');
Min.add('56');
console.log(Min.list);
console.log(Min.min())

泛型類當做參數

class User {
  username: string | undefined;
  password: string | undefined;
} 

// class MysqDb{
// add(user: User): boolean {
// console.log(user);
// return true
// }
// }
class MysqDb<T>{ // 操作泛型類
  add(user: T): boolean {
    console.log(user);
    return true
  }
} 

let U = new User();
U.username = 'zhanghu';
U.password = '123456';
let DB = new MysqDb<User>(); //把類當做是一個參數傳入泛型類裏面去
DB.add(U);

實例
功能:定義一個操作數據庫的庫,支持mysql、MongoDB
要求1:MySQL,MongoDB功能一樣,都有add, update, delete,get方法;
注意: 約束統一的規範,以及代碼的重用
解決方案: 需要約束規範要定義接口,需要重用的要用到泛型

a. 接口:在面向隊形的編程中,接口是一種規範的定義,他定義類行爲和動作的規範

b.泛型:通俗理解;泛型就是解決類 接口方法的賦值(即代碼重用)

interface DBI<T> { //規範一個接口
  add(info: T): boolean;
  update(info: T, id: number): boolean;
  delete(id: number): boolean;
  get(id: number): any[];
}
// 定義一個操作MySQL數據庫的類, 注意:要實現泛型類型接口,這個類也應該是一個泛型類
class MySqlDb<T> implements DBI<T> { //類繼承接口(受接口的約束),實現接口裏面約束的方法
  add(info: T): boolean {
     console.log(info);
     return true;
  } 

  update(info: T, id: number): boolean {
    throw new Error("Method not implemented.");
  } 

  delete(id: number): boolean {
    throw new Error("Method not implemented.");
  } 

  get(id: number): any[] {
    let list = [

    {
      width: '1080px',
      height: '960px'
  },
  {
    width: '680px',
    height: '420px'
}] 

return list;
  }
} 
// 實現操作MongoDB數據庫的類,同上
class MongoDB<U> implements DBI<U> {
  add(info: U): boolean {
    throw new Error("Method not implemented.");
  } 
  update(info: U, id: number): boolean {
    throw new Error("Method not implemented.");
  } 
  delete(id: number): boolean {
    throw new Error("Method not implemented.");
  } 
  get(id: number): any[] {
    throw new Error("Method not implemented.");
  }
} 
// 操作數據表:給用戶表添加數據,定義一個
User類做數據映射
class User {
  name: string | undefined;
  password: string | undefined;
  age?: number | undefined;
  // job: string | undefined;
} 

let U = new User();
U.name = 'zhanghu';
U.password = '123456';
U.age = 99;

let oMySql = new MySqlDb<User>(); //使用User類約束傳入數據的合法性
oMySql.add(U);
let data = oMySql.get(2);
console.log(data)

同理換成MongoDB也是一樣的用法

let oMongDB = new MongoDB<User>();即可

模塊:內部模塊,外部模塊,通過export暴露,import使用,搞清楚export 和export default的區別:一個模塊中只有一個export default,並且用使用import引入時不加{};一個模塊中有多個export,並且用使用import引入時要加{}

* 命名空間(namespace):內部模塊 主要用於組織代碼,避免命名衝突
* 模塊(modules):ts外部模塊的簡稱,側重代碼的複用,一個模塊可能會有多個命名空間;

TS中的裝飾器:就是一個方法,可以注入到類,方法,屬性參數來擴展類,屬性,方法,參數的功能;常見的裝飾器有:

類裝飾器。屬性裝飾器;

方法裝飾器;參數裝飾器裝飾器的寫法: 普通裝飾器(無法傳參),裝飾器工廠(可傳參)裝飾器是過去幾年中JS最大的成就之一,已經是es7的標準特性之一

1. 普通類裝飾器(沒有傳參)

function logClass(params: any) {
  console.log(params);
  // params 就是當前類,這時候就可以在這裏給類擴展屬性
  params.prototype.apiUrl = '動態擴展屬性';
  params.prototype.run = () => {
    console.log('我是run方法')
  }
} 

@logClass
class HttpClient {
  name: string;
  constructor(name:string){
    this.name = name;
  }
  getData() {}
} 

const http: any = new HttpClient('zhanghu');

http.run()

2. 工廠裝飾器(有傳參)

function logClass(params: any) {
  return function(target: any) {
    console.log(target);
    // console.log(params);
    target.prototype.apiUrl = params;
  }
} 

@logClass('hello') // 傳入的參數('hello 工廠裝飾器')賦給了params; 類(HttpClient)賦給target
class HttpClient {
  name: string;
  constructor(name:string){
    this.name = name;
  } 
  getData() {}
}


const http:any = new HttpClient('zhjanghu');
console.log(http.apiUrl)

2. 屬性裝飾器

屬性裝飾器表達式會在運行是當作函數被調用,傳入下列兩個參數
a. 對於靜態成員來說是類的構造函數,對於實例成員是類的原型
a. 成員的名字


// 屬性裝飾器
function logProperty(params: any) {
  return function(target: any, attr: any) {// 屬性裝飾器表達式會在運行是當作函數被調用,傳入下 
                 列兩個參數1. 對於靜態成員來說是類的構造函數,對於實例成員是累的原型;2. 成員的名字
    // console.log(target); //target代表的就是:類HttpClient

    console.log(attr);
    target[attr] = params //params的值爲:'這就是params'
  }
}

class HttpClient {
  @logProperty('這就是params')
  name: string | undefined;
  @logProperty('這是age')
  age: number | undefined;

  constructor(){} 

  getData() {
    console.log(this.name);
    console.log(this.age);
  }
} 

const http:any = new HttpClient();
http.getData();

 

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