一文搞定TS高级语法(函数 类 多态 接口 泛型 装饰器)

一、 函数

1. 定义函数

1. 函数声明

//?为可选参数 可选参数必须配置在最后面 
//可用默认参数,但不能和?用在一起
function fun1(name:string='li', age?:number):string{	//规定返回值为string类型
    return `${name}--${age}`
}
console.log(fun1('san'))
console.log(fun1('san', 10))

2. 匿名函数

let fun2 = function():void{	//无返回值
    console.log(11)
}

3. 三点运算符的应用

function sum(...res:number[]):number{	//需要存在一个数组中
    let sum:number = 0
    for(let i = 0; i<res.length; i++){
        sum += res[i]
    }
    return sum
}
console.log(sum(1,2,3))

function ali(num1:number,...num2:number[]):number{  //三点运算符要放在最后面
    return num1
}
//数组第一个值放在num1中
console.log(ali(1,2,3))

二、 类

1. 类的定义

class Person{
    name:string
    constructor(n:string){  //构造器 实例化类的时候触发的方法
        this.name = n
    }
    getName():string{
        return this.name
    }
    setName(name:string):void{
        this.name = name
    }
}
let p = new Person('li')
console.log(p.getName())
p.setName('zhang')
console.log(p.getName())

2. 类的继承

class Person{
    name:string
    constructor(n:string){  //构造函数 实例化类的时候触发的方法
        this.name = n
    }
    getName():string{
        return this.name
    }
    setName(name:string):void{
        this.name = name
    }
}
//继承
class Web extends Person{
    constructor(name:string){
        super(name) //super表示调用父类的构造函数 constructor
        //将形参name存的值传到Person构造器的n中
    }
    man(){  //不能用this.man = function(){}
        console.log('man')
    }
}
let w = new Web('wang')
console.log(w.getName())
w.man()

3. 类修饰符

1. 三种类修饰符

  • public: 公有 在类里面 子类 类外面都可以访问
  • protected: 保护类型 在类里面 子类里面可以访问
  • private: 私有 类里面可以访问

2. 修饰符实例

class Person{
    public age:number = 20
    protected name:string
    private sex:string = 'male'

    constructor(age:number, name:string, sex:string){  //构造函数 实例化类的时候触发的方法
        this.name = name
        this.age = age
        this.sex = sex
    }
    getName():string{
        return this.name
    }
    setName(name:string):void{
        this.name = name
    }
    getAge():void{
        console.log(this.age)   //类内访问
    }
}
//继承
class Web extends Person{
    constructor(age:number, name:string, sex:string){
        super(age, name, sex)
    }
    work(){
        console.log(this.name)  //访问protected name
        // console.log(this.sex) 错 不能访问
    }
}
let p = new Person(20, 'li', 'male')
console.log(p.age)  //访问public age
// console.log(p.name) 错
// console.log(p.sex)   错
let w = new Web(30, 'wang', 'female')
w.work()

4. 静态方法 实例方法 静态属性

class Per{
    public name:string = 'wang'
    static age:number = 20
    constructor(name:string){
        this.name = name
    }
    run(){          //实例方法 只能通过实例调用
        console.log(`${this.name}在运动`)
    }
    static work(){  //静态方法不能直接调用类里的属性,只能调用静态属性
        console.log(`我的年龄是${this.age}`)
    }
}
let p = new Per('wang')
p.run()
Per.work()  //静态方法可以直接调用

5. 多态的表现-重载与重写

1. 重载

1. 什么是重载

就是函数或者方法有相同的名称,但是参数列表不相同的情形,这样的同名不同参数的函数或者方法之间,互相称之为重载函数或者方法

2. 重载的作用

不用为了对不同的参数类型或参数个数,而写多个函数。多个函数用同一个名字,但参数表,即参数的个数或(和)数据类型可以不同,调用的时候,虽然方法名字相同,但根据参数表可以自动调用对应的函数

3. 重载实例
function getInfo(name:string):string
function getInfo(age:number):string
function getInfo(str:any):any{
    if(typeof str === 'string') return '我叫 ' + str
    else return '我的年龄是 ' + str
}

console.log(getInfo('zhangsan'))
console.log(getInfo(20))
//console.log(getInfo(true))    //错 没有布尔型的函数声明

//可选参数的重载
function get(name:string):string
function get(name:string, age:number):string
function get(name:any, age?:any):any{
    if(age) return '我叫 ' + name + '我的年龄是 ' + age
    else return '我叫 ' + name
}

console.log(get('li'))
// console.log(get(123)) 错误
console.log(get('li', 20))
// console.log(get('li', true))    错误

2. 重写

1. 什么是重写
  • 发生在父类与子类之间
  • 方法名,参数列表,返回类型(除过子类中方法的返回类型是父类中返回类型的子类)必须相同
  • 访问修饰符的限制一定要大于被重写方法的访问修饰符(public>protected>private)
  • 用子类中的方法代替父类中同名方法
2. 重写实例
class Animal{
    name:string
    constructor(name:string){
        this.name = name
    }
    eat(){
        console.log('吃的方法')
    }
}
class Dog extends Animal{
    constructor(name:string){
        super(name)
    }
    eat(){
        return this.name + '吃骨头'
    }
}
let d = new Dog('狗狗')
d.eat()

3. 抽象类

1. 什么是抽象类
  • 抽象类它是提供其他类继承的基类,不能直接被实例化 用abstract关键字定义抽象类和抽象方法,
  • 抽象类中的抽象方法不包含具体实现并且必须在派生类中实现,抽象方法只能放抽象类中
  • 用抽象类和抽象方法定义标准
2. 抽象类实例
abstract class Animal{
    public name:string
    constructor(name:string){
        this.name = name
    }
    abstract eat():any
}
// let a = new Animal() 错误 抽象类不能直接被实例化
class Dog extends Animal{
    //抽象类的子类必须实现抽象类中的抽象方法
    constructor(name:string){
        super(name)
    }
    changeName(){
        this.name = '阿猫阿狗'
        console.log(this.name)
    }
    eat(){
        console.log(this.name + '吃骨头')
    }
}
let d = new Dog('狗狗')
d.eat()
d.changeName()

6. 接口 约束作用

1. 属性接口

function printLabel(label:string):void{ //约束传入字符串且无返回值
    console.log('print')
}
function print(labelInfo:{label:string}):void{
    console.log('labelInfo')
}

// print('haha')    错误
// print({name: 'haha'})    错误
print({label: 'wang'})

//interface关键字定义接口
interface FullName {
    firstName: string
    secondName?: string //可选属性
}
function printName(name:FullName){  //必须传入对象firstName secondName
    console.log(name.firstName + name.secondName)
}
// printName(20,'zhang','san') 错 只能传两个字符串
let obj={
    age: 20,
    secondName: 'san',	//可以多传
    firstName: 'zhang'  //顺序可以颠倒
}
printName(obj)  //可以

//接口实例作用 封装 ajax
//约束了属性的名字和类型
interface Config{
    type:string
    url:string
    data?:string
    dataType:string
}
function ajax(config:Config){
    let xhr = new XMLHttpRequest()
    xhr.open(config.type, config.url, true )
    xhr.send(config.data)
    xhr.onreadystatechange = function(){
        if(xhr.readyState === 4 && xhr.status === 200){
            console.log('success')
//JSON.stringify()的作用是将 JavaScript 对象转换为 JSON 字符串,而JSON.parse()可以将JSON字符串转为一个对象。
            if(config.dataType === 'json') JSON.parse(xhr.responseText)
            else console.log(xhr.responseText)
        }
    }
}
ajax({
    type:'get',
    data:'name=zhangsan',
    url:'www.baidu.com',
    dataType:'json'
})

2. 函数类型接口

//对方法传入的参数及返回值进行约束
interface encrypt{
    (key:string, value:string):string
}
//名可以不同 但是类型得相同
let md5:encrypt = (keys, values) => {
    return keys + values
}
console.log(md5('name', 'zhang'))	//得传入两个string

3. 可索引接口

//对数组、对象的约束
var arr:number[] = [222,333] 正常定义数组的方式
var arr1:Array<string> = ['222','333']

interface UserArr{
    [index:number]:string   //number是索引值的数据类型 string是value的数据类型
}
let arr:UserArr = ['aaa', 'bbb']
console.log(arr[0])

interface UserObj{
    [index:string]:string | number
}
let obj:UserObj = {name:'张三', age:20}

4. 类类型接口

//对类的约束 和 抽象类有点类似
interface Animal{
    name:string
    eat(str:string):void
}
//implements 使用类接口
class Dog implements Animal{
    name:string
    constructor(name:string){
        this.name = name
    }
    eat(){  //没有参数也可以
        console.log(this.name + '吃骨头')
    }
}
let d = new Dog('狗狗')
d.eat()
class Cat implements Animal{
    name:string
    constructor(name:string){
        this.name = name
    }
    eat(food:string){  //没有参数也可以
        console.log(this.name + '吃骨头')
    }
}
let c = new Cat('喵喵')
c.eat('food')

5. 接口继承接口

interface Animal{
    getName():void
}
interface Person extends Animal{
   getFood():void
}
class Web implements Person{
    name:string
    food:string
    constructor(name:string, food:string){
        this.name = name
        this.food = food
    }
    getName(){
        console.log(this.name)
    }
    getFood(){
        console.log(this.name + '吃' + this.food)
    }
}
let w = new Web('小李', '米')
w.getFood()

6. 继承结合接口

class Pro{
    work:string
    constructor(work:string){
        this.work = work
    }
}
class Code extends Pro implements Person{
    constructor(name:string, food:string, work:string){
        super(work)
    }
    getName(): void {
    }
    getFood(): void {
    }
}

7. 泛型

1. 泛型函数

function getData<T>(value:T):T{
    return value
}
getData<number>(123)
getData<string>('123')
//或者可以将返回值设为any
function getNum<T>(value:T):any {
    return '1233'
}
getNum<number>(123)

2. 泛型类

class MinClass<T>{
    public list:T[] = []
    add(num:T){
        this.list.push(num)
    }
    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 m = new MinClass<number>()  //实例化类并且指定了T代表的类型是number

3. 泛型接口

//写法1
interface ConfigFn{
    <T>(value:T):T
}
let getData:ConfigFn = function<T>(value:T):T{
    return value
}
getData<string>('12')
//写法2
interface Config<T>{
    (value:T):T
}
function getData<T>(value:T):T{
    return value
}
let myGetData:Config<string> = getData
myGetData('2000')

4. 把类作为参数来约束数据传入的类型

//平常做法
class User{
    username:string | undefined
    password:string | undefined
}
class MysqlDB{
    add(user:User):boolean{
        console.log(user)
        return true
    }
}
let u = new User()
u.username = '张三'
u.password = '123'
let db = new MysqlDB()
db.add(u)

class User{
    username:string | undefined
    password:string | undefined
}
class MysqlDB<T>{
    add(info:T):boolean{
        console.log(info)
        return true
    }
}
let u = new User()
u.username = '张三'
u.password = '123'
let db = new MysqlDB<User>()    //验证
db.add(u

8. 装饰器

1. 什么是装饰器

  • 装饰器 可以注入到类 方法 属性参数上来扩展类 属性 方法 参数的功能
  • 装饰器写法 普通装饰器(无法传参) 装饰器工场(可传参)

2. 类装饰器

//在类声明之前被声明 紧靠着类声明
//普通装饰器
function logClass(params:any){
    console.log(params) //params就是当前类
    params.prototype.apiURL = '动态扩展的属性'
    params.prototype.run = function(){
        console.log('这是一个run方法')
    }
}

@logClass
class HttpClient{
    constructor(){}
    getData(){}
}
let http:any = new HttpClient()
console.log(http.apiURL)
http.run()

//装饰器工厂
function logClass(params:any){
    return class extends params{
        apiURL:string = '修改后的api'
        getData(){
            this.apiURL = this.apiURL + '--'
            console.log(this.apiURL)  //如果里面
        }
    }
}

@logClass
class HttpClient{
    public apiURL:string | undefined
    constructor(){
        this.apiURL = '修改前的api'
    }
    getData(){
        console.log(this.apiURL)
    }
}
let http:any = new HttpClient()
console.log(http.apiURL)
http.getData()

3. 属性装饰器

function logProperty(params:any){
    return function(target:any, attr:any){
        console.log(target) //指向类
        console.log(attr)   //指向要修饰的属性
        target[attr] = params
    }
}
class HttpClient{
    @logProperty('修改后的api')
    public url:any | undefined
    constructor(){}
    getData(){
        console.log(this.url)
    }
}
let p = new HttpClient()
p.getData()

4. 方法装饰器

function get(params:any){
    return function(target:any, methodName:any, desc:any){
        console.log(target)
        console.log(methodName)
        console.log(desc)
        target.apiURL = '新增api'
        target.run = function(){
            console.log('新增方法')
        }
    }
}
class HttpClient{
    public url:any | undefined
    constructor(){}
    @get('www.baidu.com')
    getData(){
        console.log(this.url)
    }
}
let http:any = new HttpClient()
console.log(http.apiURL)
http.run()*/
//方法装饰器将数组全部变成字符串
function get(params:any){
    return function(target:any, methodName:any, desc:any){
        console.log(target)
        console.log(methodName)
        console.log(desc)
        let oMethod = desc.value
        desc.value = function(...args:any[]){   //这么写是替换desc.value
            args = args.map((value)=>{  //而不是重写
                return String(value)
            })
            console.log(args)
            oMethod.apply(this, args)   //重写
        }
    }
}
class HttpClient{
    public url:any | undefined
    constructor(){}
    @get('www.baidu.com')
    getData(...args:any[]){
        console.log(args)
        console.log('我是getData里面的方法')
    }
}
let http:any = new HttpClient()
http.getData(123, 'xx')

5. 参数装饰器

function logParams(params:any){
    return function(target:any, methodName:any, paramsIndex:any){
        console.log(params)
        console.log(target)
        console.log(methodName)
        console.log(paramsIndex)
        target.apiURL = params
    }
}
class HttpClient{
    public  url:any | undefined
    constructor(){}
    getData(@logParams('xx') uuid:any){
        console.log(uuid)
    }
}
let http:any = new HttpClient()
http.getData('123')
console.log(http.apiURL)

6. 装饰器注意点

  • 装饰器执行顺序 属性>方法>方法参数>类
  • 同一种装饰器由后向前 后近向远执行
  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值