关于学习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();

 

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