TypeScript看完就会了

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

-- 安装
npm install -g typescript

检查是否安装成功 
tsc -v 
1
2
3
4
5
编译

-- 将.ts文件转换成.js文件
tsc 文件名.ts
1
2
VsCode配置TypeScript
vscode配置TypeScript文件的自动编译

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

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

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


vscode监视tsconfig报错
1.管理员身份运行vs code

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

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

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

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

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

布尔类型(boolean)
// 布尔类型(boolean) 
let flag:boolean = false;
console.log(flag);
1
2
3
数值类型(number)
// 数值类型(number)
let num:number = 20;
console.log(num);

// 如果没有值不是number类型那么ts编译会报错 但是浏览器可以正常输出
// let num1:number = "20";
// console.log(num1);
1
2
3
4
5
6
7
字符串类型(string)
// 字符串类型(string)
let str:string = "Hello";
console.log(str);
1
2
3
数组类型(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","me"];
console.log(arr2);
1
2
3
4
5
6
7
8
9
10
11
12
13
元组类型(tuple)
// 元组类型(tuple) 属于数组的一种 为数组的每一个元素指定一个类型
let arr3:[string,number,boolean] = ["this",1,true];
console.log(arr3);
1
2
3
枚举类型(enum)
// 枚举类型(enum)
/* 
    声明方式
    enum 枚举名{
        标识符=[值]
    }
*/

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
任意类型(any)
// 任意类型(any) 可以随意指定类型
let sum:any = 123;
sum = "456";
console.log(sum);

1
2
3
4
5
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);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void类型
// void类型 :typescript中的void表示没有任何类型,一般用于定义函数的时候函数没有返回值
// 指定foo函数没有返回值
function foo():void{
    console.log("void");
}
foo();

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

1
2
3
4
5
6
7
8
9
10
11
12
13
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")})();


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
函数
函数定义
// 函数定义
// 定义无返回值
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());

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
函数参数
// 函数参数 在参数后面指定参数的类型
function fun4(name:string){
    return name;
}
console.log(fun4("小牛"));

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
默认参数
// 默认参数  
// 在参数定义时给它赋上默认值 
function fun6(name:string,age:number=20):any{
    return `${name}---${age}`;
}
console.log(fun6("小牛",21));

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

1
2
3
4
5
6
7
8
9
10
11
函数重载
// 函数重载 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));

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
箭头函数
// 箭头函数 es6箭头函数一样
setTimeout(()=>console.log("箭头函数的this依然指向上下文"));

1
2
3

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,age);
    }
    M.prototype = Man.prototype;
    var m = new M("奶牛",21);
    m.run();
    m.work();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
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)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
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();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
类的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());


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
继承
继承使用关键字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();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
访问修饰符
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,sex:string){
        super(name,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();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
静态成员
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();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
多态
多态 :父类定义的方法不一定实现,让继承它的子类去实现,每个子类都有不同的表现形式

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();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
抽象类
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();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
接口
接口:是一种规范的定义,它定义了行为和动作的规范,接口起到了一种限制和规范的作用,接口定义了某一批类所需要的遵循的规范,接口不关心这些类的内部状态数据,也不关心这些类里方法实现的细节,它只规定了这批类必须提供某些方法,提供了这些方法的类就可以满足实际需要,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))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
可索引接口
可索引接口用来约束数组的格式

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


1
2
3
4
5
6
7
8
9
对象约束
// 对象的约束
interface Obj{
    [key:string]:any
}
const obj:Obj = {"name":"小牛"}
console.log(obj["name"])

1
2
3
4
5
6
7
可选操作符
属性?:数据类型

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
类类型接口
// 类类型接口  约束类
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();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
联合类型和接口
// 联合类型和接口
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)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
接口封装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"
})


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
函数类型接口
函数类型接口:对方法传入的参数以及返回值进行约束

// 函数类型接口

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

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

1
2
3
4
5
6
7
8
9
10
11
12
接口继承
接口可以继承另一个接口来扩展自己

// 接口继承  接口可以通过其他接口来扩展自己
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();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
泛型
泛型:软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。

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

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

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


1
2
3
4
5
6
7
8
9
泛型类
// 泛型类
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())

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
泛型接口
// 泛型接口
// 函数型接口泛型
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>("小牛");


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
装饰器
装饰器是一种特殊类型的声明,它能够被附加到类,方法,属性或参数上,可以修改类的行为,通俗的讲装饰器就是一个方法,可以注入到类,方法,性或参数上来扩展类、方法,属性或参数的功能。常见的装饰器有:类装饰器,方法装饰器,属性装饰器,参数装饰器。
装饰器的写法:普通装饰器(无法传参),装饰器工厂(可传参),装饰器是过去几年中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();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
装饰器:工厂装饰器(可传参)

// 类装饰器:工厂装饰器(可以传参)
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
3
4
5
6
7
8
9
10
11
12
13
14
15
属性装饰器
属性装饰器会被应用到属性描述上,可以用来监视,修改或替换属性的内容

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

​ 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)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
方法装饰器
方法装饰器会被应用到方法描述上,可以用来监视、修改或者替换方法定义

方法装饰器会在运行时传入下列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)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
方法参数装饰器
参数装饰器表达式会在运行时当作函数被调用,可以使用参数装饰器为类的原型增加一些元素数据 ,传入下列3个参数:

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

2.方法的名字。

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

function logParam(param:any){
    return function(target: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)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
装饰器执行顺序
装饰器执行顺序 : 属性装饰器 ————> 方法装饰器 ————> 方法参数装饰器 ————> 类装饰器

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

模块化优点:

防止命名冲突
代码复用性
高维护性
模块化主要由 import 和 export 构成

export 模块对外暴露
import 引入暴露的模块
export
单个暴露

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

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

1
2
3
4
5
6
7
统一暴露

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

1
2
3
4
5
6
默认暴露

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

1
2
3
4
5
6
7
8
Import
默认引入

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

1
2
3
解构赋值引入

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

1
2
3
针对于默认暴露引入

import m2 from "./export3";

1
2
命名空间
命名空间:在代码量较大的情况下,为了避免各种变量命名相冲突,可将相似功能的函数、类、接口等放置到命名空间内,同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();


————————————————
原文链接:https://blog.csdn.net/weixin_45764643/article/details/116465126

装饰器:https://ninghao.net/blog/7384

原文地址:https://blog.csdn.net/thlzjfefe" target="_blank" rel="noopener" title="thlzjfefe">thlzjfefe</a> <img class="article-time-img article-heard-img" src="https://csdnimg.cn/release/blo

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


原文连接:https://www.cnblogs.com/dupd/p/5951311.htmlES6之前已经出现了js模块加载的方案,最主要的是CommonJS和AMD规范。commonjs主要应用于服务器,实现同步加载,如nodejs。AMD规范应用于浏览器,如requirejs,为异步加载。同时还有CMD规范,为同步加载方案如seaJS。ES6在语言规格的层面上,实现了模块功能,而且...
以为Es6,javascript第一次支持了module。ES6的模块化分为导出(export)与导入(import)两个模块,其中在项目中,我们会经常看到一种用法import * as obj from,这种写法是把所有的输出包裹到obj对象里。示例一 1 2 3 4 5 6 7 // index.js export function fn1(data){ console.log(1) } export f.
视频讲解关于异步处理,ES5的回调使我们陷入地狱,ES6的Promise使我们脱离魔障,终于、ES7的async-await带我们走向光明。今天就来学习一下 async-await。async-await和Promise的关系经常会看到有了 async-await、promise 还有必要学习吗、async await优于promise的几个特点,接收了这些信息后,就蒙圈了。现在才知道...
TypeScript什么是TypeScript?TypeScript是由微软开发的一款开源的编程语言TypeScript是JavaScript的超集,遵循最新的ES5 ES6规范,TypeScript扩展了JavaScript的语法TypeScript更像后端 Java c# 这样的面向对象语言可以让js开发大型企业项目谷歌也在大力支持TypeScript的推广,React ,VUE 都集成了TypeScriptTypeScript安装安装-- 安装npm install -g type
export class AppComponent { title = 'Tour of heroes'; hero: Hero = { id: 1, name: '张三' };}export class Hero { id: number; name: string;}就是这一段,看起来有点晕,这里是实例化一个Hero类型的对象hero,还是创建一个变量?后面是赋值,但是不知道什么意思?hero: Hero = { id: 1, na.
用 async/await 来处理异步昨天看了一篇vue的教程,作者用async/ await来发送异步请求,从服务端获取数据,代码很简洁,同时async/await 已经被标准化,是时候学习一下了。先说一下async的用法,它作为一个关键字放到函数前面,用于表示函数是一个异步函数,因为async就是异步的意思, 异步函数也就意味着该函数的执行不会阻塞后面代码的执行。 写一个async 函数async function timeout() {return 'hello world'
es6的语法已经出了很长的时间了,在使用上也可以通过babel这类的编译工具转译为浏览器可以识别的es5的语法,但是依旧有很多开发在写代码的时候,依旧没有用es6的语法,而是习惯使用老的语法,这篇文章主要会介绍解构赋值基本用法以及在实际使用场景中相比es5语法的优势,让大家从根本上了解es6语法的优势基本用法数组解构让我们一起先来看数组解构的基本用法:let [a, b, c] ...
参考链接1 参考链接2写法1 - 使用 function 关键字function greeter(fn: (a: string) =&gt; void) { fn("Hello, World");}function printToConsole(s: string) { console.log(s);}greeter(printToConsole);(a: string) =&gt; void上述语法的含义:表示一个函数,接收一个字符串作为输入参数,没有返回参数。可
ES6简介-ECMAScript是javascript标准-ES6就是ECMAScript的第6个版本-ECMAScript6.0(以下简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了。它的目标,是使得JavaScript语言可以用来编写复杂的大型应用程序,成为企业级开发语言。ES6新增加的功能:1.let
ES6  在ES5的基础上增加了一些新的特性和写法,特别在函数写法上,增加了箭头函数 1.正经的函数写法//普通的传递值的写法functionsum1(x,y){returnx+y;}constres=sum1(2,3);console.log(res);//传递对象的方式,调用时需要传递一个对象过去function
ES5及ES6es表示ECMASCript,他是从es3,es5,es6,es5是2009.12月发布的,es6是2015.6月发布的。vue2完全支持es5的(vue3完全支持es6的),react完全支持es6es5的新特性严格模式(对应的相反的称为怪异模式)'usestrict'//一般用于相关的设计上面书写一个严格模式底下的代码就需要按照严格模
ES5的严格模式所谓严格模式,从字面上就很好理解,即更严格的模式,在这种模式下执行,浏览器会对JS的要求更苛刻,语法格式要求更细致,更符合逻辑。怪异模式:就是我们之前一直使用的开发模式,就叫怪异模式。因为很多时候出来的结果是非常怪异的,所以才称之为怪异模式。'usestrict'//一般用
相同点export与exportdefault均可用于导出常量、函数、文件、模块可在其它文件或模块中通过import+(常量|函数|文件|模块)名的方式,将其导入,以便能够对其进行使用不同点一、在一个文件或模块中,export、import可以有多个,exportdefault仅有一个//model.jsle
24.class类 25.class中的extend 26.super关键字 27.super应用 28.class属性 30.静态成员和实例成员 31.构造函数问题 32.构造函数原型 33.原型链 34.js查找机制 35.原型对象中this指向 36.扩展内置对象方法 37.call方法 38.借用父构造函数
什么是ES6ES的全称是ECMAScript,它是由ECMA国际标准化组织,制定的一项脚本语言的标准化规范。泛指2015年发布的es2015版极其后续版本ES6中新增语法letES6中新增的用于声明变量的关键字。注意:使用let关键字声明的变量才具有块级作用域,使用var声明的变量不具备块级作用域特
命名修饰符let:不能重复声明变量、块级作用域leta=1;leta=2;//报错const:初始化常量,必须给初始值,否则报错、在同一个作用域内,const定义的常量不能修改其值、块级作用域consta=10a=100//报错,不能重复声明解构constobj={name:'jack'age:18sex:'
ES6新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。1{2leta=10;3varb=1;4}56a//ReferenceError:aisnotdefined.7b//1上面代码在代码块之中,分别用let和var声明了两个变量。然后在代码块之外调用
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><metahttp-equiv="X-UA-Compatib
一,RegExp构造函数es5中,RegExp构造函数的参数有两种情况。1,参数是字符串,第二个参数表示正则表达式的修饰符(flag)。2,参数是一个正则表达式,返回一个原有正则表达式的拷贝。es6中,如果RegExp构造函数第一个参数是一个正则对象,那么可以使用第二个参数指定修饰符。而
一、字符的Unicode表示法JavaScript允许采用\uxxxx形式表示一个字符,其中xxxx表示字符的Unicode码点。表示法只限于码点在\u0000~\uFFFF之间的字符,超过该范围需要用两个双字节表示ES6改进:将码点放入大括号,就能正确解读该字符。转换参考:https://blog.csdn.net/hezh1994/ar