美文网首页
JS中bind、call和apply的作用以及在TS装饰器中的用

JS中bind、call和apply的作用以及在TS装饰器中的用

作者: 鹏多多 | 来源:发表于2021-11-22 09:28 被阅读0次

    1,前言


    bindcallapply在函数式编程时候非常有用,本文旨在记录一下我遇到过的一些用法和知识点,也记录一下在装饰器中的用法。

    1,call


    call() 方法使用一个指定的this值和单独给出的一个或多个参数来调用一个函数。它的第一个参数是你需要指向的this目标,后面的参数是你需要传递的参数,无参数可以不写。

    语法:

    function.call(target, arg1, arg2, ...)
    

    1.1,例子

    如下,控制台会打印出:快看【张三】在奔跑

    const Person = {
      Name: '张三',
      Run() {
        return `快看【${this.Name}】在奔跑`
      }
    }
    
    const Animal = {
      Name: '猛犸象'
    }
    
    console.log(Person.Run()) // 打印出:快看【张三】在奔跑
    

    让我们使用call改变下this指向

    1.2,直接调用

    如果没有传递第一个参数,this的值将会被绑定为全局对象,也就是window对象(浏览器环境)。由于在window上找不到this.Name这个属性,控制台会打印出:快看【undefined】在奔跑

    console.log(Person.Run.call()) // 打印出:快看【undefined】在奔跑
    

    1.3,将this指向另一个对象

    此时this会绑定为被指向的对象,控制台会打印出:快看【猛犸象】在奔跑

    console.log(Person.Run.call(Animal)) // 打印出:快看【猛犸象】在奔跑
    

    1.4,传递参数

    const Person = {
      Name: '张三',
      Run(param1, param2) {
        console.log(param1)
        console.log(param2)
        return `快看【${this.Name}】在奔跑`
      }
    }
    
    const Animal = {
      Name: '猛犸象'
    }
    
    console.log(Person.Run.call(Animal, 10, '100')) // 打印出:10、'100'、快看【猛犸象】在奔跑
    

    2,apply


    apply()方法调用一个具有给定this值的函数,以及以一个数组(或类数组对象)的形式提供的参数。它的第一个参数是你需要指向的this目标,后面的参数是你需要传递的数组参数,无参数可以不写。

    语法:

    function.apply(target, [argsArray])
    

    2.1,例子

    如下,控制台会打印出:快看【张三】在奔跑

    const Person = {
      Name: '张三',
      Run() {
        return `快看【${this.Name}】在奔跑`
      }
    }
    
    const Animal = {
      Name: '猛犸象'
    }
    
    console.log(Person.Run()) // 打印出:快看【张三】在奔跑
    

    让我们使用apply改变下this指向

    2.2,直接调用

    如果没有传递第一个参数,this的值将会被绑定为全局对象,也就是window对象(浏览器环境)。由于在window上找不到this.Name这个属性,控制台会打印出:快看【undefined】在奔跑

    console.log(Person.Run.apply()) // 打印出:快看【undefined】在奔跑
    

    2.3,将this指向另一个对象

    此时this会绑定为被指向的对象,控制台会打印出:快看【猛犸象】在奔跑

    console.log(Person.Run.apply(Animal)) // 打印出:快看【猛犸象】在奔跑
    

    2.4,传递参数

    const Person = {
      Name: '张三',
      Run(...arg) {
        console.log(arg)
        return `快看【${this.Name}】在奔跑`
      }
    }
    
    const Animal = {
      Name: '猛犸象'
    }
    console.log(Person.Run.apply(Animal, [10, '100'])) // 打印出:[10、'100']、快看【猛犸象】在奔跑
    

    2.5,合并数组

    let arr = ['a', 'b']
    let elements = [0, 1, 2]
    array.push.apply(arr, elements)
    console.log(arr) // ["a", "b", 0, 1, 2]
    

    3,bind


    bind()方法创建一个新的函数,在bind()被调用时,这个新函数的this被指定为bind()的第一个参数,而其余参数将作为新函数的参数,供调用时使用。

    语法:

    function.bind(target, arg1, arg2, ...)
    

    3.1,例子

    如下,控制台会打印出:快看【张三】在奔跑

    const Person = {
      Name: '张三',
      Run() {
        return `快看【${this.Name}】在奔跑`
      }
    }
    
    const Animal = {
      Name: '猛犸象'
    }
    
    console.log(Person.Run()) // 打印出:快看【张三】在奔跑
    

    让我们使用apply改变下this指向

    3.2,直接调用

    如果没有传递第一个参数,this的值将会被绑定为全局对象,也就是window对象(浏览器环境)。由于在window上找不到this.Name这个属性,控制台会打印出:快看【undefined】在奔跑

    注意:bind返回的是一个方法,需要加上()执行才行

    console.log(Person.Run.bind()()) // 打印出:快看【undefined】在奔跑
    

    3.3,将this指向另一个对象

    此时this会绑定为被指向的对象,控制台会打印出:快看【猛犸象】在奔跑

    console.log(Person.Run.bind(Animal)()) // 打印出:快看【猛犸象】在奔跑
    

    3.4,传递参数

    const Person = {
      Name: '张三',
      Run(param1, param2) {
        console.log(param1)
        console.log(param2)
        return `快看【${this.Name}】在奔跑`
      }
    }
    
    const Animal = {
      Name: '猛犸象'
    }
    console.log(Person.Run.bind(Animal, 996, '100')()) // 打印出:996 '100' 快看【猛犸象】在奔跑
    

    4,TypeScript中装饰器使用


    使用bind或者apply或者call,可以将方法装饰器中的this指向被装饰的方法,不影响原方法使用的同时,注入新的逻辑处理。

    function GetHttp(param: string) {
      return function (target: any, Name: any, desc: any): void {
        console.log(target) // 原型
        console.log(Name) // 方法名
        console.log(desc) // 方法描述 desc.value即是该方法
        const ev = desc.value
        desc.value = function(): void {
          console.log('我是改写后的function')
          ev.call(this)
        }
      }
    }
    
    class HttpGet {
      name: string
      constructor(name: string) {
        this.name = name
      }
      @GetHttp('方法装饰器')
      request(): void {
        console.log(this.name)
      }
    }
    
    const HttpObj = new HttpGet('小红')
    HttpObj.request()
    
    // 打印出:方法装饰器、我是改写后的function、小红
    

    5,总结


    5.1,相同点

    • 都可以通过指定第一个参数,改变this指向
    • 都可以传递参数

    5.2,不同点

    • bind返回的是一个函数,需要加上()来执行
    • apply传递参数需要数组的形式

    如果看了觉得有帮助的,我是@鹏多多11997110103,欢迎 点赞 关注 评论;
    END

    PS:在本页按F12,在console中输入document.querySelectorAll('._2VdqdF')[0].click(),有惊喜哦

    往期文章

    个人主页

    相关文章

      网友评论

          本文标题:JS中bind、call和apply的作用以及在TS装饰器中的用

          本文链接:https://www.haomeiwen.com/subject/jvgvtrtx.html