学习记录1-TS

135 阅读11分钟

2022年5月21日 TypeScript

今天是第一记录学习进度,之前学习的效果并不好,收获只是了解了一些概念代码能力并没有进步,希望之后能有所改变。
今天计划初步学习一下,TS

TS在VScode中的自动编译

在tsconfig中设置js代码编译目录"outdor"配置
终端->运行任务->tsc:监视

类型注解

一种轻量级的为函数或者变量添加的约束

使用webpack打包TS

配置出现版本问题,,,不想换低版本node开摆
被舍友蛊惑去看动画片了...睡觉前上传一次

2022年5月22日

基本类型

srting number boolean 不知道该记些什么
ts中变量一开始是什么类型,后期赋值时只能用这个类型的数据

undedined和null

都可以作为其他类型的子类型,如赋值给number类型的变量

let num2: number = undefined
console.log(num2)

数组和元组

数组定义方式1:
let 变量名:数据类型[]=[值s]
let arr1:number[] = [10,20,30,40,50]
数组定义方式2:泛型
let 变量名: Array<数据类型> = [值s]
let arr2:Array<number> = [100,200,300]
注意:数组定义后,里面的数据类型必须和定义数组时的类型时一致的

元组:在定义元组时,就限定了类型和数据的个数
let arr3:[string,number,boolean] = ['学习',999.999,true]
注意:元组类型在使用的时候,数据类型的位置和数据的个数与定义时保持一致如:
console.log(arr3[0].split('')) //split分割数组的方法
console.log(arr3[1].toFixed(2)) //toFixed保留两位小数

枚举

enum类型是对JavaScript标准数据类型的一个补充

enum Color{
    red,
    green,
    blue
  }
  // 定义一个Color的枚举类型的变量来接收枚举的值
  let color:Color = Color.red
  console.log
  console.log(Color.red,Color.green,Color.blue)

any

为在编程阶段还不清楚的类型的变量指定类型,可能来自动态的内容,比如用户输入或第三方代码库

let str:any = 100
str='有点不想学了...'
console.log(str)
// 当一个数组中要存储多个数据,个数不确定,类型不确定,此时也可以使用any来定义数组
let arr: any[] = [100,'我不想学习了',true]

void

表示没有任何类型,当一个函数没有返回值时,通常其返回值类型是:void

// 在函数声明的时候,小括号后面使用;void,代表的是该函数没有任何返回值
function showMsg():void{
console.log('我爱学习')

}
console.log(showMsg())

object

object表示非原始类型

// object类型
// 定义一个函数,参数是object类型,返回值也是object类型
function getObj(obj:object):object{
console.log(obj)
return{
    name:'卡卡西',
    age:27
}
}
console.log(getObj({name:'佐助',age:'18'})

联合类型

表示取值可以为多种类型中的一种

// 定义一个函数得到一个数字或字符串值得字符串形式值
function getString(str:number|string):string{
 return str.toString()
console.log(getString('123'))
}

// 定义一个函数得到一个数字或字符串值的长度
function getString(str:number|string):number{
return str.toString().length
}
console.log(getString('012345678'))

类型断言

编译器相信我,我知道自己在写什么 <类型>变量名
或 值 as 类型

类型推断

没有指定类型定义的时候会根据变量值推断一个类型

接口

接口时对象的状态(属性)和行为(方法)的抽象(描述),是一种类型,是一种规则,是一个能力一种约束

(()=>{
// 定义一个接口,该接口作为Person对象的类型使用,可以限定或者是约束该对象中的属性数据
interface IPerson{
readonly id:number // id是只读的
name:string
age:number
sex?:string // ? 问号代表是可有可无的 ,没有不会报错
}
// 定义一个对象,该对象的类型就是定义的接口IPerson
const person:IPerson={
id:1,
name:'学习哥',
age:18,
sex:'男'
}
})()

函数类型

为了使用接口表示函数类型,需要给接口定义一个调用签名就是一个小括号,里面写函数的参数
通过接口的方式,作为函数的类型使用

// 定义一个接口,用来作为某个函数的类型使用
interface ISearchFunc{
// 定义一个调用签名
    (source:string,subString:string):boolean
}
// 定义一个函数,该类型就是上面定义的接口
const searchString:ISearchFunc = function (source:string,subString:string):boolean{
// 在source字符串中查找subString这个字符串
return source.search{subString} > -1
}

// 调用函数
console.log(searchString('学习','学'))

类类型

让类实现接口,可以把接口看作是类的类型

// 定义一个接口
interface IFly{
// 该方法没有实现
    fly()
}
// 定义一个接口,这个类的类型就是上面定义的接口(IFly接口约束了当前这个Person类)
class Person implements IFly{ 
 // 实现接口中的方法
     fly()
        console.log('大概这样下去可以')
}
// 实例化对象
const person = new Person()
persong.fly()

// 一个类可以被多个接口约束
class Person2 implements IFly,ISwim{
fly(){
    console.log('学习')
}
swim(){
    console.log('还是'){
    }
}
// 实例化对象
const person2 = new Person2()
person2.fly()
person2.swim()

类可以通过接口的方式,来定义当前类的类型,类可以实现多个接口,接口中的内容需要正真实现

接口可以继承其他多个接口
interface IMyFlyAndSwim extends IFly, ISwim { }

// 定义一个类,直接实现IMyflyAndSwim这个接口
class Person3 implements IMyFlyAndSwim{
 fly(){
    console.log('学习')
}
swim(){
    console.log('还是'){
    }
}
const Person3 = new Person3()
person3.fly()
person3.swim()

接口和接口之间叫继承 类和接口之间叫实现

可以理解为模板,通过模板可以实例化对象

// ts中类的定义及使用
class Person{
    // 定义属性
    name:string
    // 定义构造函数:为了将来实例化对象的时候,可以直接对属性的值进行初始化
    constructor(name:string){
    // 更新对象中的属性数据
    this.name = name
}
// 定义实例方法
sayHi(){
        console.log(`${this.name}爱学习`)
    }
}
// ts中使用类,实例化对象,可以直接进行初始化操作
const person = new Person('我')

继承

类与类之间的关系
A类继承B类,A类叫子类,B类叫基类 也叫派生类和超类

// 定义一个类,作为基类
    class Person{
    // 定义属性
    name:string
    age:number
    // 定义构造函数
    constructor(name:string,age:number)
    this.neam= name
    this.age = age
    }
    // 定义实例方法
    sayHi(str:string){
        console.log(`我是:$(this.name},${str}`}
    }
    }
    
    // 定义一个类,继承自Person
    class Student extends Person{
        constructor(ame:string,age:number){
        // 调用父类中的构造函数,使用的是super
            super(name,age) 
        }
        // 可以调用父类中的sayHi方法
        sayHi(){
            super.sayHi('哈哈')
        }
    }
    
    // 实例化Person
    const person = new Person('学习','18')
    person.sayHi('学习')
    // 实例化Student
    const stu = newStudent('大学习',81)
    stu.sayHi()

子类中可以用super调用父类中的构造函数和实例方法 子类中可以重写父类方法

2022年 5月23日

多态

父类型的引用指向子类型的对象,不同类型的对象针对相同的方法,产生了不同的行为

// 定义一个父类
class Animal{
    // 定义一个属性
    name:string
    // 定义一个构造函数
    constructor(name:string){
    // 更新属性
    this.name = name
    }
    // 实例方法
    run(distance:number){
    console.log(`跑了$(distance)米`)
    }
}
// 定义一个子类
class Dog extends Animal{
 // 构造函数
 constructor(name){
     // 调用父类的构造函数,实现子类中属性的初始化操作
     super(name)
 }
 // 实例方法,重写父类中的实例方法
     run(distance:number = 5){
    console.log(`跑了$(distance)米`)
    }
}
// 再定义一个子类
class Pig extends Animal{
 // 构造函数
 constructor(name){
     // 调用父类的构造函数,实现子类中属性的初始化操作
     super(name)
 }
 // 实例方法,重写父类中的实例方法
     run(distance:number = 10){
    console.log(`跑了$(distance)米`)
    }
}
// 实例化父类对象1
const ani : Animal = new Animal('动物')
ani.run()
// 实例化子类对象
const dog:Dog = new Dog('大黄')
dog.run()

// 实例化对象
const pig:Pif = new Pig('八戒')
pig.run()
========================================================
// 父类和子类的关系:父子关系,此时,父类类型创建子类对象
const dog1:Animal = new Dog('小黄')
dog1.run()
const pig1:Animal = new Pig('佩奇')
pig1.run()
// 该函数需要的参数是Animal类型的
function showRun(ain:Animal){
    ani.run()
}
showRun(dog1)
showRun(pig1)

类中的成员修饰符

修饰符(类中的成员修饰符):主要是描述类中的成员(属性,构造函数,方法)的可访问性

// 类中的成员都有自己默认的访问修饰符,public
// private修饰符,类中的成员如果使用private来修饰,呢么外部无法访问这个成员数据包括子类
// protucted 外部无法访问,但是子类可以访问
我们可以在下面改
class Person{
    // 属性
    private name:string // 私有的类外部不能访问 
    // 构造函数
    constructor(name:string){
        this.name = name
    }
    // 方法
    eat(){
    console.log('我真的真的爱学习',this.name)
    }
}

    // 实例化对象
    const per = new Person('哈哈')
    // 在类的外部可以访问类的属性成员
    console.log(per.name)
    per.eat()

readonly修饰符

首先是一个关键字,可以对类中的属性成员进行修饰,该成员就不能在外部被随意修改了
readonly写在成员前面
构造函数中,可以对只读的属性成员的数据进行修改
构造函数中的参数可以使用readonly,public,privte,protected修饰,会出现对应的属性成员

// 定义一个类型
class Person{
// 属性
readonly name:string
constructor(name:string){
    this.name = name
}
sayHi(){
    console.log('我爱学习',this.name)

    }
}
// 实例化对象
const person : Person = new Person('学习')
person.name = '加油学习' //  上面加了readonly这里就会报错
console.log(person)
console.log(person.name)

存取器

TS支持通过getters/setters来截取对象成员的访问,可有效控制对象成员的访问

// 外部可以传入姓氏和名字数据,同时使用set和get控制姓名的数据,外部也可以修改操作
class Person{
    firstName:string
    lastName:string
    csonstructor(firstName:string,lastName:string)
    this.firstName = firstName
    this.lastName  = lastName
    // 姓名的成员属性
    
    // 读取器
    get fullName(){
        return this.fistName+'_'+this.lastName
    }
    // 设置器
    set fullName(){
       // 获取后重新赋值给firstName和lastName
       let names = val.split('_')
       this.firstName = names[0]
       this.lastName = names[1]
    }
}
// 实例化对象
const person:Person = new Person('我爱','学习')
// 获取该属性成员属性
console.log(person.fullName)
// 设置该属性的数据
person.fullName = '学习_爱我'

静态成员

在类中通过static修饰的属性或者方法,就是静态属性及静态方法,也称之为静态成员

// 定义一个类
class Person{
// 静态属性
// 类中默认有一个内置的name属性
    static name1:string
    static constructor(){
    // 此时this是实例对象,name1是静态属性,不能通过实例对象直接调用静态属性
        // this.name1 = name
        
    }
    sayHi(){
        console.log('我爱学习')
    }
}

// 实例化对象
const person:Person = new Person()
// 通过实例对象调用的实例属性
console.log(person.name1)
// 调用的实例方法
person.sayHi()
// 通过类名.静态属性的方法来设置该成员数据
Person.sayHI()

抽象类

包含抽象方法(抽象方法一般没有任何具体内容的事件),也可以包含实例方法,抽象类不能被实例化
抽象类的作用就是为子类服务,让子类进行实例化及实现内部的抽象方法

// 定义一个抽象类
abstract class Animal{
// 抽象方法
abstract eat(){
注意!里面不能有具体实现
}
// 实例方法
sayHi(){
    console.log('滚去学习')
  } 
}
// 定义一个子类Dog
class Dog extends Animal{
// 重新实现抽象类中的方法,此时这个方法就是当前Dog类的实例方法
    eat(){
        console.log('就算是狗也要学习')
    }
}

// 实例化dog对象
const dog:Dog = new Dog()
dog.eat()
// 调用抽象类中的实例方法
dog.sayHi()

// 不能实例化抽象类的对象
// const ani:Animal = new Animal()

函数

封装了一些重复使用的代码,在需要的时候直接调用

// 函数声明,命名函数
function add (x:string,y;string):string{  //求和的函数
    return x+y
}
// 函数表达式,匿名函数
let add2 = function (x:number,y:number):number{
    return x+y
}
// 函数完整写法
const add3:(x:number,y:number) => number=function(x:number,y:number):number{
return x+y
9
}

可选参数和默认参数

// 定义一个函数
const getFullNameZ = function(firstName:string='学习',lastName:string):string{
     // 判断名字是否传入
    if(lastName){
        return fitstName + '_' + lastName
    }else{
        return firstName
    }
}
// 函数调用
console.log(getFullName('习学'))

可选参数:函数在声明的时候,内部的参数使用了?修饰,表示该参数可以传入也可以不传入

剩余参数(rest参数)

函数声明时剩余参数是放在所有参数最后的
// ...args:string[] 表示剩余参数,放在了一个字符串的数组中,args里面
function showMsg(str:string,...args:string)

函数重载

函数名字相同,函数的参数及个数不同

// 函数重载声明
    function add(x:string,y:string):string
    function add(x:number,y:number):number

// 定义一个函数
function add (x:string|number,y:string|number):string|number{
    if(typeof x === 'string' && typeof y === 'string'){
        return x + y // 字符串拼接
    }else if(typeof x === 'number' && typeof y === 'number'){
        return x + y // 数字相加
    }
}

// 函数调用
// 两个参数都是字符串
console.log(add('我爱','学习'))
// 两个参数都是数字
console.log(add(10,20))
// 如果传入非法数字  如果没有上面的重载限制就会报错
console.log(add(100,'真好'))

泛型

在定义函数、接口、类的时候不能预先确定要使用的类型

// 定义一个函数传入两个参数,第一个时数据,第二个数量,作用是根据数量产生对应个数的数据,放进数组
// 定义函数 
// 可以传入任意类型的数据,返回的是存储这个任意类型数据的数组
function getArr<T>(value:T,const:T):T[]{
     // 根据数据和数量产生一个数组
     const arr : T[]=[]  // 或者const arr:Array<T>
     for(let i = 0 ; i<count;i++){
         arr.push(value)
     }
     return arr
}
const arr1 = getArr4<number>(200,3)
  我敲不下去了...我得缓缓 

 

多个泛型参数的函数

函数中有多个泛型的函数

function getMsg<K,V>(value1:K,value2:V):[K,V]{
    return[value1,value2]
}
const arr1 = getMsg<string,number>('jack','100.235')
console.log(arr1[0].split(''),arr1[1].toFixed(1)) // split('')拆分字符串

泛型接口

定义接口时指定泛型类型,使用接口时再指定具体的泛型类型

// 定义一个用户类,通过类的实例对象调用相关方法可以添加多个信息对象,调用getUserId方法可以根据id获取某个指定的用户信息对象
// 定义一个泛型接口
interface IBaseCRUD<T>{
    data : Array<T>
    add : (t:T)=>T
    getUserId : (id: number)=>T
}
class User{
    id?:number // ?代表可有可无
    name:string 
    age:number
    // 构造函数
    constructor(name:string,age:number){
        this.name = name
        this.age = age
    }
}
// 定义一个类,增加和查询
class UserCRUD implements IBaseCRUD<User>{
    // 用来保存多个User类型的用户信息
    data : Array<User>=[]
    add(user:User):User
        // 产生id
        user.id = Data.now() + Math.random()
        // 把用户信息对象添加到data数组中
        this.data.push(user)
        return user
    // 方法用来存储用户信息对象的
    getUserId(id:number)
    // 方法根据id查询指定的用户对象
    getUserId(id:number): User{
        return this.data.find(user => user.id === id)
    }
}
// 实例化添加用户信息对象的类UserCRUD
const userCRUD : UserCRUD = new UserCRUD()
// 调用添加数据的方法
userCRUD.add(new User('jack',20))
userCRUD.add(new User('lucy',19))
console.log(userCRUD.data)

泛型类

class GenericNumber<T>{
    // 默认的属性的值的类型是泛型类型
        defaultValue:T
        add:(x:T,y:T) => T
}
// 实例化类的对象的时候,再确定泛型的类型
const g1 : GenericNumber<number> = new GenericNumber<number>()
// 设置属性值
g1.defaultValue = 100
// 相加的方法
g1.add = function(x,y)
     return x + y

基础结束