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

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传递参数需要数组的形式

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


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


面向百度编程

公众号

weixinQRcode.png

往期文章

个人主页

posted @ 2021-11-22 09:27  鹏多多  阅读(2010)  评论(0编辑  收藏  举报