TypeScript看完就会了

TypeScript

什么是TypeScript?

  1. TypeScript是由微软开发的一款开源的编程语言
  2. TypeScript是JavaScript的超集,遵循最新的ES5 ES6规范,TypeScript扩展了JavaScript的语法
  3. TypeScript更像后端 Java c# 这样的面向对象语言可以让js开发大型企业项目
  4. 谷歌也在大力支持TypeScript的推广,React ,VUE 都集成了TypeScript

TypeScript安装

安装

-- 安装
npm install -g typescript

检查是否安装成功 
tsc -v 

编译

--.ts文件转换成.js文件
tsc 文件名.ts

VsCode配置TypeScript

vscode配置TypeScript文件的自动编译

  1. 在.ts文件夹下运行cmd 执行 tsc --init 命令 自动生成tsconfig.json配置文件

    更改tsconfig.json配置文件 “outDir”: “./js”, 编译后js输出的目录

在这里插入图片描述

  1. 任务 ——>运行任务 ——> 监视tsconfig.json 文件

在这里插入图片描述

vscode监视tsconfig报错

1.管理员身份运行vs code

2.在终端执行:get-ExecutionPolicy,显示Restricted

3.在终端执行:set-ExecutionPolicy RemoteSigned

4.在终端执行:get-ExecutionPolicy,显示RemoteSigned


数据类型

TypeScript中为了使编写的代码更规范,更利于维护,增加了类型校验,在声明变量同时为它指定数据类型

格式 : 变量名: 数据类型 = 值

布尔类型(boolean)

// 布尔类型(boolean) 
let flag:boolean = false;
console.log(flag);

数值类型(number)

// 数值类型(number)
let num:number = 20;
console.log(num);

// 如果没有值不是number类型那么ts编译会报错 但是浏览器可以正常输出
// let num1:number = "20";
// console.log(num1);

字符串类型(string)

// 字符串类型(string)
let str:string = "Hello";
console.log(str);

数组类型(Array)

// 数组类型(Array) 直接为数组的每个元素指定同一类型

// 数组声明方式一  数组声明时指定 数组类型
let arr:number[] = [1,2,3,4];
console.log(arr);

// 数组声明方式二  Array数组类型 给它指定泛型
let arr1:Array<string> = ["1","2","3"];
console.log(arr1);

// 数组声明方式三 any类型
let arr2:any[] = ["this",0,"me"];
console.log(arr2);

元组类型(tuple)

// 元组类型(tuple) 属于数组的一种 为数组的每一个元素指定一个类型
let arr3:[string,number,boolean] = ["this",1,true];
console.log(arr3);

枚举类型(enum)

// 枚举类型(enum)
/* 
    声明方式
    enum 枚举名{
        标识符=[值]
    }
*/

enum Color{
    red,
    blue,
    yellow="yellow"
}
// 如果枚举没有给枚举元素赋值那么指向的是当前元素的下标
console.log(Color.blue);
// 给枚举元素赋值 直接输出当前元素的值
let y:Color = Color.yellow;
console.log(y);

任意类型(any)

// 任意类型(any) 可以随意指定类型
let sum:any = 123;
sum = "456";
console.log(sum);

null和undefined

// null和undefined 其他类型(never类型)数据类型的子类型
// 声明未赋值 undefined
let str1:string;
console.log(str1); // 输出 undefined 但是 ts编译会报错

// 指定string 或 undefined 如果不赋值 输出undefined编译不会出错
let str2: string | undefined = "Hello";
console.log(str2);

// null 类型 只能为null
let str3:null = null;
console.log(str3);

// 为一个元素指定多种类型
let str4:string | undefined | null;
str4 = "Hello";
console.log(str4);

void类型

// void类型 :typescript中的void表示没有任何类型,一般用于定义函数的时候函数没有返回值
// 指定foo函数没有返回值
function foo():void{
    console.log("void");
}
foo();

// 指定函数返回值类型
function get():number{
    return 100;
}
console.log(get());

never类型

// never类型:是其他类型(包括null,undefined)的子类型,代表从来不会出现的值,
// 这意味着never声明的变量只能被never类型所赋值
var a:undefined;
a = undefined;
console.log(a);

var b:null;
b = null;
console.log(b);

// 从未出现的值  一般never类型不常用
var err:never;
err = (()=>{throw new Error("Error")})();



函数

函数定义

// 函数定义
// 定义无返回值
function fun():void{
    console.log("void")
}
fun();

const fun1 = function():void{
    console.log("字面量函数void")
}
fun1();

// 定义带返回值的函数
function fun2():string{
    return "返回值类型是string";
}
console.log(fun2());

const fun3 = function():string{
    return "字面量函数带返回值";
}
console.log(fun3());

函数参数

// 函数参数 在参数后面指定参数的类型
function fun4(name:string){
    return name;
}
console.log(fun4("小牛"));

可选参数

// 可选参数  
// 有时候需要age这个参数 有时候不需要 我们可以给age设置可选
function fun5(name:string,age?:number):any{
    // 如果有age这个参数 我们返回 name 和 age
    if(age){
        return `${name} --- ${age}`;
    }
    // 如果没有我们只返回name
    return `${name}`;
}
console.log(fun5("牛小牛",22));

// 注意:可选参数尽量写在形参列表最后

默认参数

// 默认参数  
// 在参数定义时给它赋上默认值 
function fun6(name:string,age:number=20):any{
    return `${name}---${age}`;
}
console.log(fun6("小牛",21));

剩余参数

// 剩余参数 ... 用于参数列表不确定参数个数使用
// 注意:剩余参数写在形参列表最后
function fun7(a:number,...result:number[]){
    let num:number = a;
    for(let v of result){
        num += v;
    }
    return num;
}
console.log(fun7(1,2,3,4,5));

函数重载

// 函数重载 ts支持函数重载
// 函数重载 : 函数名相同参数列表不同(参数的个数,顺序,类型)有一个不同就都不相同
function getInfo(name:string):string;
function getInfo(age:number):number;
function getInfo(str:any):any{
    if(typeof str === "string"){
        return str;
    }else{
        return str;
    }
}
console.log(getInfo("hello"))

// 多个参数重载
function getData(name:string):string;
function getData(name:string,age:number):any;
function getData(name:string,age?:number):any{
    if(age){
        return `${name} --- ${age}`;
    }
    return `${name}`
}
console.log(getData("小牛",22));

箭头函数

// 箭头函数 es6箭头函数一样
setTimeout(()=>console.log("箭头函数的this依然指向上下文"));


ES5类

 // es5类

    // 最简单的类
    function Student(){
        this.name = "小牛";
        this.age = 20;
    }
    const s = new Student();
    console.log(s.name);

    console.log("-----------------------")

    // 构造函数和原型链上增加方法
    function Person(){
        this.name = "小牛";
        this.age = 21;
        this.run = function(){
            console.log(this.name + "在运动");
        }
    }
    // 原型链上的属性会被多个实例共享 构造方法不会
    Person.prototype.sex = "man";
    Person.prototype.work = function(){
        console.log(this.name + "在工作");
    }
    var p = new Person();
    console.log(p.name);
    p.run();
    p.work();

    console.log("-----------------------")


    // 类里面的静态方法
    function Stu(){
        this.name = "小牛"; // 属性
        this.age = 21;
        this.run = function(){ // 实例方法
            console.log(this.name + "在运动");
        }
    }
    // 静态方法只能被类调用 不能被实例调用
    Stu.getInfo = function(){
        console.log("我是静态方法")
    }
    // var stu = new Stu();
    // stu.getInfo();
    // 类 调用静态方法
    Stu.getInfo();

    console.log("-----------------------")



    // 冒充继承
    function Girl(){
        this.name = "MM";
        this.age = 20;
        this.run = function(){
            console.log(this.name + "运动")
        }
    }
    // 原型链
    Girl.prototype.color = "pink";
    Girl.prototype.work = function(){
        console.log(this.name + "工作")
    }

    // Web类 继承Girl类 原型链 + 冒充继承
    function Web(){
        // 对象冒充继承 call apply bind
        Girl.call(this);
    }
    var w = new Web();
    // 冒充继承可以继承构造函数的属性和方法
    w.run();
    // 冒充继承可以继承构造函数中的属性和方法 但是不能继承原型链的属性和方法
    // w.work(); 
    console.log("-----------------------")



    //  原型链实现继承 继承Girl类

    function Father(){
        this.name = "牛小牛";
        this.age = 22;
        this.run = function(){
            console.log(this.name + "运动");
        }
    }
    Father.prototype.work = function(){
        console.log(this.name + "工作")
    }


    function Man(){

    }
    // 原型链继承 可以继承构造函数的属性和方法,也可以继承原型链上的属性方法
    Man.prototype = new Father();
    var m = new Man();
    console.log(m.age);
    m.run();
    m.work();

    console.log("-----------------------")

    // 原型链继承的问题?
    function F(name,age){
        this.name = name;
        this.age = age;
        this.run = function(){
            console.log(this.name + "运动")
        }
    }
    F.prototype.sex = "man";
    F.prototype.work = function(){
        console.log(this.name + "工作")
    }
    var f = new F("花花牛",21);
    f.work();

    function FF(name,age){

    }
    FF.prototype = new F();
    var ff = new FF("雨花雨",21);
    // 原型链继承传参的问题
    ff.run();

    console.log("-----------------------")


    // 原型链 + 冒充继承组合继承模式
    function P(name,age){
        this.name = name;
        this.age = age;
        this.run = function(){
            console.log(this.name + "运动")
        }
    }
    P.prototype.sex = "man";
    P.prototype.work = function(){
        console.log(this.name + "工作")
    }
    function PP(name,age){
        P.call(this,name,age);
    }
    PP.prototype = new P();
    var pp = new PP("雨花雨",22);
    pp.run();
    pp.work();

    console.log("-------------------------")

    // 原型链 + 冒充继承的另一种方式

    function Man(name,age){
        this.name = name;
        this.age = age;
        this.run = function(){
            console.log(this.name + "运动")
        }
    }
    Man.prototype.sex = "man";
    Man.prototype.work = function(){
        console.log(this.name + "工作")
    }
    function M(name,age){
        Man.call(this,name,age);
    }
    M.prototype = Man.prototype;
    var m = new M("奶牛",21);
    m.run();
    m.work();

ES6类

  // 类的声明
    class Person{
        // 构造函数
        constructor(name,age) { 
            this.name = name;
            this.age = age;
        }
        // 定义方法
        show(name){
            console.log(this.name + "显示")
        }
    }
    let p = new Person("小牛",21);
    console.log(p.name);
    console.log(p.age);
    p.show();

    console.log("------------------------------")

    // 静态成员
    class Phone{
        // static 修饰的属性和方法都是静态的只属于类
        static name = "Phone";
        static show(){
            console.log("静态方法")
        }
    }
    // 静态成员不能被实例化
    console.log(Phone.name);
    Phone.show();

    console.log("------------------------------")

    // 继承 extends super
    class A{
        constructor(name,age){
            this.name = name;
            this.age = age;
        }
        eat(){
            console.log("吃饭")
        }
    }

    class B extends A{
        constructor(name,age,color,size){
            super(name,age);
            this.color = color;
            this.size = size;
        }
        // 重写父类的方法
        eat(){
            console.log("吃晚饭")
        }
    }
    const b = new B("小牛",20,"skyblue",180);
    console.log(b.name);
    b.eat();

    console.log("------------------------------")


    // get set 方法 
    class Smart{
        // 用来获取属性的方法
        get price(){
            return "get方法获取属性"
        }
        // set 的时候 需要传入一个参数
        set price(newValue){
            console.log("set方法设置了属性")
        }
    }
    const smart = new Smart();
    smart.price = "set方法设置";
    console.log(smart.price)

TS类的声明

// ts 类的声明
class Person{
    name:string;  // 属性 默认public修饰 
    age:number;
    constructor(name:string,age:number){ // 构造函数 实例化的时候触发
        this.name = name;
        this.age = age;
    }
    show():void{
        console.log(this.name + "ts类中的方法")
    }
}
const person = new Person("小牛",21);
console.log(person.name);
console.log(person.age);
person.show();

类的get set方法

get 和 set方法用于获取和设置类的属性

// 类的get set方法
class Student{
    name:string;
    constructor(name:string) {
        this.name = name;
    }
    // 用来设置属性的值
    setName(name:string):void{
        this.name = name;
    }
    // 用来获取属性的值
    getName():string{
        return this.name;
     }
}
const student = new Student("大牛");
// 获取没有设置之前的值
console.log(student.getName());
// 设置值
student.setName("二牛")
// 获取设置之后的值
console.log(student.getName());


继承

继承使用关键字extends,调用父类使用super,子类继承父类的属性和方法,并且子类可以改写父类的属性和方法

// 类的继承 extends super
class Phone{
    brand:string;
    price:number;
    constructor(brand:string,price:number){
        this.brand = brand;
        this.price = price;
    }
    show():void{
        console.log("Phone.show");
    }
}
class SmartPhone extends Phone{
    color:any;
    size:any;
    constructor(brand:string,price:number,color:any,size:any){
        super(brand,price);
        this.color = color;
        this.size = size;
    }
    // 重写父类的方法
    show():any{
        console.log("SmartPhone.show")
    }
}
const smartPhone = new SmartPhone("iphoneX",7999,"black",5.5);
console.log(smartPhone.brand);
console.log(smartPhone.price);
console.log(smartPhone.color);
console.log(smartPhone.size);
smartPhone.show();

访问修饰符

typescript为我们提供了三种访问修饰符

public 公共的 作用范围 本类 子类 类外部

protected*保护的 作用范围 本类 子类

​ private 私有的 作用范围 本类

// 访问修饰符
/*
    public 公共的  作用范围  本类 子类 类外部
    protected 保护的  作用范围  本类 子类 
    private 私有的  作用范围  本类
*/ 

class School{
    public name:string;
    protected age:number;
    private sex:string;
    constructor(name:string,age:number,sex:string){
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
    show():any{
        console.log("public---->" + this.name)
        console.log("protected---->" + this.age)
        console.log("private---->" + this.sex)
    }
}
const school = new School("xiaoniu",21,"man");
console.log(school.name);
school.show();
// age sex 分别是用 protected  private 在类外部不能访问所以编译出错
// console.log(school.age);
// console.log(school.sex);
class Teacher extends School{
    constructor(name:string,age:number,sex:string){
        super(name,age,sex);
    }
    show():any{ 
        console.log("public---->" + this.name)
        console.log("protected---->" + this.age)
        // sex 是private修饰的 继承过来的 sex是无法访问的所以会报错
        console.log("private---->" + this.sex)
    }
}
const teacher = new Teacher("daniu",22,"sex");
console.log(teacher.name);
teacher.show();

静态成员

static修饰的静态成员当类加载时就存在 只能被类调用 不能实例化

// 静态成员
// 静态成员当类加载时就存在 不能被实例化
class Per {
    public name:string;
    public age:number;
    // static声明 静态属性
    static sex:any = "man";
    constructor(name:string,age:number) {
        this.name = name;
        this.age = age;
    }
    static eat():void{
        console.log("静态方法")
    }
}
const p = new Per("小牛",21);
console.log(p.name)
// 静态成员只能被类调用
console.log(Per.sex)
Per.eat();

多态

多态 :父类定义的方法不一定实现,让继承它的子类去实现,每个子类都有不同的表现形式

class Animal{
    public name:string;
    constructor(name:string){
        this.name = name;
    }
    eat(){
        console.log("吃的方法!")
    }
}
class Dog extends Animal{
    constructor(name:string){
        super(name);
    }
    eat(){
        console.log(this.name + "吃骨头")
    }
}
const dog = new Dog("小狗狗");
dog.eat();

class Cat extends Animal{
    constructor(name:string){
        super(name);
    }
    eat(){
        console.log(this.name + "吃猫粮")
    }
}
const cat = new Dog("小花猫");
cat.eat();

抽象类

typescript中的抽象类:它是提供其他类继承的基类,不能被直接实例化

abstract 关键字修饰的抽象类和抽象方法, 抽象类中的抽象方法不包含具体的实现并且必须在派生类中实现

abstract 修饰的方法只能在抽象类中

// 抽象类
abstract class Animal {
    public name:any;
    constructor(name:any){
        this.name = name;
    }
    abstract eat():any;
    // 非抽象方法 子类可以不实现它
    say(){
        console.log(this.name + "在说话")
    }
}

class Dog extends Animal{
    constructor(name:any){
        super(name);
    }
    // 抽象类的子类必须实现抽象类的抽象方法
    eat(){
        console.log(this.name + "吃骨头")
    }
}

class Cat extends Animal{
    constructor(name:any){
        super(name);
    }
    eat(){
        console.log(this.name + "吃猫粮")
    }
}
const cat = new Cat("小花猫");
cat.eat();


接口

接口:是一种规范的定义,它定义了行为和动作的规范,接口起到了一种限制和规范的作用,接口定义了某一批类所需要的遵循的规范,接口不关心这些类的内部状态数据,也不关心这些类里方法实现的细节,它只规定了这批类必须提供某些方法,提供了这些方法的类就可以满足实际需要,typescript中的接口类似于java,同时还增加了更灵活的接口属性,包括属性,函数,可索引和类等。

json约束

约束了json的格式

// 接口 interface

interface Conn{
    host:string;
    port:number;
    username:string;
    password:string
}

// 约束了参数 及参数类型
function Connection(info:Conn):any{
    return `${info.host} --- ${info.port} --- ${info.username} --- ${info.password}`;
}
// 第一种传参方式
 Connection({
     host:"localhost",
     port:3306,
     username:"root",
     password:"root"
 })

const conn = {
    host:"localhost",
    port:3306,
    username:"root",
    password:"root"
}

// 第二种传参方式
console.log(Connection(conn))

可索引接口

可索引接口用来约束数组的格式

// 可索引接口 约束数组
interface Arr{
    // 约束数组 下标为number类型 的一个string类型数组
    [index:number]:string;
}
const ones:Arr = ["A","B","C"];
console.log(ones[0])


对象约束

// 对象的约束
interface Obj{
    [key:string]:any
}
const obj:Obj = {"name":"小牛"}
console.log(obj["name"])

可选操作符

属性?:数据类型

表示可选 可以写也可以不写 可以通过编译

interface IPerson{
    firstName:string,
    // ? 可选操作符 
    lastName?:string,
    sayHi:()=>string
}
// 接口约束对象
const customer:IPerson = {
    firstName:"Tom",
    lastName:"Tim",
    sayHi:():string=> "Hi Tom"
}
console.log(customer);

类类型接口

// 类类型接口  约束类
interface Cla{
    name:string;
    eat():any;
}

// 类类型接口  类只能用 implements 实现
class Birage implements Cla{
    public name = "goods";
    eat(){
        console.log("吃东西")
    }
}
const br = new Birage();
console.log(br.name)
br.eat();

联合类型和接口

// 联合类型和接口
interface RunOptions{
    program:string;
    commandline:string[] | string | (()=>string);
}
const options:RunOptions = {
    program:"tim",
    
    // 参数可以是字符串数组
    // commandline:[
    //     "小牛",
    //     "大牛"
    // ]

    // 参数可以使字符串
    // commandline:"Hi"

    // 参数可以是箭头函数
    commandline:()=>"Hi Tim"
}
console.log(options.program)
console.log(options.commandline)

接口封装ajax

// 封装ajax
interface Config{
    type:string;
    url:string;
    data?:string;
    dataType:string
}

function Ajax(config:Config):any{
    const xhr = new XMLHttpRequest();

    // 创建连接
    xhr.open(,config.type,config.url);

    // 发送请求
    xhr.send();

    xhr.onreadystatechange = function(){
        if(xhr.readyState == 4 && xhr.status == 200){
            console.log("成功")
            if(config.dataType == "json"){
                console.log(JSON.parse(xhr.responseText))
            }else{
                console.log(xhr.responseText)
            }
        }
    } 
}
Ajax({
    url:"http://localhost:8080/heroall",
    type:"get",
    dataType:"json"
})


函数类型接口

函数类型接口:对方法传入的参数以及返回值进行约束

// 函数类型接口

interface encrypt{
    // 没有函数体 
    (Key:string,value:string):string;
}

var md5 = function(Key:string,value:string):string{
    return Key + "<--->" + value; 
}
console.log(md5("root","root"))

接口继承

接口可以继承另一个接口来扩展自己

// 接口继承  接口可以通过其他接口来扩展自己
interface Andy{
    eat():void;
}
interface anfn extends Andy{
    work():void;
}
class Program{
    age:number;
    constructor(age:number){
        this.age = age;
    }
    coding():void{
        console.log(this.age + "年龄加载")
    }
}
class Aniy extends Program implements anfn{
    name:string;
    constructor(age:number,name:string){
        super(age);
        this.name = name;
    }
    eat():void{
        console.log(this.name + "吃东西")
    }
    work():void{
        console.log(this.name + "工作")
    }
}
const aniy = new Aniy(20,"小牛");
aniy.coding();
aniy.eat();
aniy.work();


泛型

泛型:软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。

在像C#和Java这样的语言中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件。

通俗理解:泛型就是解决 类 接口 方法的复用性、以及对不特定数据类型的支持(类型校验)

泛型函数

// 泛型拯救了 any  泛型可以支持不特定的数据类型
// T 代表泛型 
function getDatas<T>(value:T):T{
    return value;
}
console.log(getDatas<number>(123));
console.log(getDatas<string>("小牛"));


泛型类

// 泛型类
class MinClass<T>{
    public list:T[] = [];

    add(value:T){
        this.list.push(value);
    }

    min():T{
        var minNum = this.list[0];
        for(let i=0;i<this.list.length;i++){
            if(minNum>this.list[i]){
                minNum = this.list[i];
            }
        }
        return minNum;
    }
}
// 实例化传入的 number类型决定了 他真正的类型
var m1 = new MinClass<number>();
m1.add(1);
m1.add(2);
m1.add(3);
m1.add(4);
console.log(m1.min())

泛型接口

// 泛型接口
// 函数型接口泛型
interface ConfigFn{
    <T>(value:T):T;
}
var getFn:ConfigFn = function<T>(value:T):T{
    return value;
}
getFn<number>(1);

// 泛型接口
interface getData2<T>{
    (value:T):T;
}
var getData2 = function<T>(value:T):T{
    return value;
}
getData2<string>("小牛");



装饰器

装饰器是一种特殊类型的声明,它能够被附加到类,方法,属性或参数上,可以修改类的行为,通俗的讲装饰器就是一个方法,可以注入到类,方法,性或参数上来扩展类、方法,属性或参数的功能。常见的装饰器有:类装饰器,方法装饰器,属性装饰器,参数装饰器。
装饰器的写法:普通装饰器(无法传参),装饰器工厂(可传参),装饰器是过去几年中JS最大的成就之一,已是ES7的标准特性之一

类装饰器

类装饰器:普通装饰器(无法传参)

// 类装饰器 : 普通装饰器 (不能传参)

function logClass(params:any){ 
    console.log(params); // params 代表当前类
    params.prototype.name = "普通装饰器的属性";
    params.prototype.run = function(){
        console.log("普通装饰器原型动态添加方法")
    }
}

@logClass
class HttpClient{
}
const http:any = new HttpClient();
console.log(http.name);
http.run();

装饰器:工厂装饰器(可传参)

// 类装饰器:工厂装饰器(可以传参)
function logClass(param:string){
    return function(target:any){
        console.log(target) // target 当前类
        console.log(param) // param 当前类传进来的参数
        target.prototype.url = param;
    }
}
@logClass("http:www.xiaoniuniu.com")
class HttpClient{

}
var httpClient:any = new HttpClient();
console.log(httpClient.url); 

属性装饰器

属性装饰器会被应用到属性描述上,可以用来监视,修改或替换属性的内容

属性装饰器会在运行时传入两个参数

​ 1.对于静态成员来说是类的构造函数,对于实例来说是类的原型对象

​ 2.成员的名字

// 属性装饰器
function logProperty(params:any){ // params就是当前类传递进来的参数
    return function(target:any,attr:any){
        console.log(target)
        console.log(params)
        target[attr] = params;
    }
}

class HttpClient{
    @logProperty("http:www.niuxiaoniu.com")
    public url :any | undefined;

    getData(){
        console.log(this.url);
    }
}
var http = new HttpClient()
console.log(http.url)

方法装饰器

方法装饰器会被应用到方法描述上,可以用来监视、修改或者替换方法定义

方法装饰器会在运行时传入下列3个参数

1.对于静态成员来说是类的构造函数,对于实例成员是类的原型对象

2.成员的名字

3.成员的属性描述符

function get(param:any){
    return function(target:any,methodName:any,desc:any){
        console.log(target)
        console.log(methodName)
        console.log(desc)
        target.urlAPI = param;
        target.run = function(){
            console.log("方法装饰器")
        }
    }
}

class HttpClient{
    url : any | undefined;
    constructor(){

    }
    @get("http://www.niuxiaoniu.com")
    getData(){
        console.log(this.url)
    }
}
const http:any = new HttpClient();
console.log(http.urlAPI)


方法参数装饰器

参数装饰器表达式会在运行时当作函数被调用,可以使用参数装饰器为类的原型增加一些元素数据 ,传入下列3个参数:

1.对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。

2.方法的名字。

3.参数在函数参数列表中的索引。

function logParam(param:any){
    return function(target:any,methodName:any,paramIndex:any){
        console.log(target)
        console.log(methodName)
        console.log(paramIndex)
        target.urlAPI = param;
    }
}
class HttpClient{
    getData(@logParam("123456") uuid:any){
        console.log(uuid);
    }
}
const http:any = new HttpClient();
http.getData(123456);
console.log(http.urlAPI)


装饰器执行顺序

装饰器执行顺序 : 属性装饰器 ————> 方法装饰器 ————> 方法参数装饰器 ————> 类装饰器

模块化

模块化是将一个大的程序,拆分成多个小文件,然后将小文件组合起来

模块化优点:

  • 防止命名冲突
  • 代码复用性
  • 高维护性

模块化主要由 import 和 export 构成

  • export 模块对外暴露
  • import 引入暴露的模块

export

单个暴露

// 单独暴露 在需要暴露的内容前面加入 export关键字
export let school = "我爱学习";

export function getData(){
    console.log("我可以改变你")
}

统一暴露

let msg = "嘿嘿";
function getMsg(){
    console.log("哈哈")
}
export {msg , getMsg};

默认暴露

// 默认暴露 以对象形式暴露
export default{
    name:"Hello",
    show(){
        console.log("Hello Show");
    }
}

Import

默认引入

// 引入 将暴露的内容全部引入 并赋值给m1
import * as m1 from "./export";

解构赋值引入

// 解构赋值形式引入
import {msg,getMsg} from "./export2";

针对于默认暴露引入

import m2 from "./export3";

命名空间

命名空间:在代码量较大的情况下,为了避免各种变量命名相冲突,可将相似功能的函数、类、接口等放置到命名空间内,同Java的包,TypeScript的命名空间可以将代码包裹起来,只对外暴露需要在外部访问的对象,命名空间内的对象通过export关键字对外暴露

命名空间和模块的区别:

  • 命名空间:内部模块,主要用于组织代码,避免命名冲突。
  • 模块:ts的外部模块的简称,侧重代码的复用,一个模块里可能会有多个命名空间
namespace A{
    interface Animal {
        name: string;
        eat(): void;
    }
    export class Dog implements Animal {
        name: string;
        constructor(name: string) {
            this.name = name;
        }
        eat(): void {
            console.log(`${this.name} ---- 吃骨头!!!`);
        }
    }
    export class Cat implements Animal {
        name: string;
        constructor(name: string) {
            this.name = name;
        }
        eat(): void {
            console.log(`${this.name} ----吃猫粮!!!`);
        }
    }
}
const aDog = new A.Dog("小狗狗");
aDog.eat();

const aCat = new A.Cat("小喵喵");
aCat.eat();


  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值