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(),有惊喜哦


公众号

往期文章

个人主页

JS中bind、call和apply的作用以及在TS装饰器中的用法的更多相关文章

  1. python_如何修改装饰器中参数?

    案例: 为分析程序内哪些函数执行时间开销较大,我们需定义一个带timeout参数的装饰器 需求: 统计被装饰函数的运行时间 时间大于timeout时,将此次函数调用记录到log日志中 运行时可以修改t ...

  2. 快速理解js中的call,apply的作用

    今天被人问到js中的call,apply的区别和用途,解释了一番后,想到之前在逼乎上看到一位小伙伴生动形象的解释 本身不难理解,看下MDN就知道了,但是不常用,遇到了,还要脑回路回转下.或者时间长了, ...

  3. python装饰器中@wraps作用--修复被装饰后的函数名等属性的改变

    Python装饰器(decorator)在实现的时候,被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变),为了不影响,Python的functools包中提供了一个叫wraps的de ...

  4. 【转】odoo 新API装饰器中one、model、multi的区别

    http://blog.csdn.net/qq_18863573/article/details/51114893 1.one装饰器详解 odoo新API中定义方式: date=fields.Date ...

  5. 装饰器中functools的用处

    定义一个最简单的装饰器 def user_login_data(f): def wrapper(*args, **kwargs): return f(*args, **kwargs) return w ...

  6. 装饰器中的@functools.wraps的作用

    def login_required(view_func): @functools.wraps(view_func) def wrapper(*args, **kwargs): ...... retu ...

  7. python装饰器中functools.wraps的作用详解

    直接上代码看效果: # 定义一个最简单的装饰器 def user_login_data(f): def wrapper(*args, **kwargs): return f(*args, **kwar ...

  8. python装饰器中的计时器thd.strat用法

    thd = KThread(target=_new_func, args=(), kwargs=new_kwargs) thd.start() thd.join(seconds) alive = th ...

  9. JSP和Servlet中的几个编码的作用及原理

    首先,说说JSP和Servlet中的几个编码的作用. 在JSP和Servlet中主要有以下几个地方可以设置编码,pageEncoding="UTF-8".contentType=& ...

随机推荐

  1. java 文档自动生成的神器 idoc

    写文档 作为一名开发者,每个人都要写代码. 工作中,几乎每一位开发者都要写文档. 因为工作是人和人的协作,产品要写需求文档,开发要写详细设计文档,接口文档. 可是,作为一个懒人,平时最讨厌的一件事情就 ...

  2. 题解 [APIO2013]道路费用

    link Description 幸福国度可以用 N 个城镇(用 1 到 N 编号)构成的集合来描述,这些城镇 最开始由 M 条双向道路(用 1 到 M 编号)连接.城镇 1 是中央城镇.保证一个 人 ...

  3. 云原生的弹性 AI 训练系列之三:借助弹性伸缩的 Jupyter Notebook,大幅提高 GPU 利用率

    Jupyter Notebooks 在 Kubernetes 上部署往往需要绑定一张 GPU,而大多数时候 GPU 并没有被使用,因此利用率低下.为了解决这一问题,我们开源了 elastic-jupy ...

  4. Java:ConcurrentHashMap类小记-1(概述)

    Java:ConcurrentHashMap类小记-1(概述) 对 Java 中的 ConcurrentHashMap类,做一个微不足道的小小小小记,分三篇博客: Java:ConcurrentHas ...

  5. 记一个非常诡异的关于 shared_ptr 的 bug

    问题描述 今天写项目的时候遇见一个特别诡异的 bug,体现在在执行某条语句时,程序会莫名崩溃,并且给出的错误信息也非常难懂,只有一个malloc(): invalid size (unsorted)错 ...

  6. [对对子队]会议记录5.18(Scrum Meeting5)

    今天已完成的工作 何瑞 ​ 工作内容:搭建第8关 ​ 相关issue:搭建关卡7.8.9 ​ 相关签入:feat:初步搭建了Lv8 吴昭邦 ​ 工作内容:搭建第8关 ​ 相关issue:搭建关卡7.8 ...

  7. 热身训练1 ping ping ping

    点此进入 题意: 一棵树,n+1 个节点,以0号节点为根,给出端点(a,b),节点a到节点b的路径上,至少有一个点是"坏掉的",求"坏掉的点"最少 分析: St ...

  8. InitSpatialMetaData()速度慢的问题

    解决方法:with sqlite3.connect(dbfile) as con: con.enable_load_extension(True) con.execute("SELECT l ...

  9. Linux零基础之shell基础编程入门

    从程序员的角度来看, Shell本身是一种用C语言编写的程序,从用户的角度来看,Shell是用户与Linux操作系统沟通的桥梁.用户既可以输入命令执行,又可以利用 Shell脚本编程,完成更加复杂的操 ...

  10. 零基础小白要如何跟好的学习嵌入式Linux(转)

    作为一个新人,怎样学习嵌入式Linux?被问过太多次,特写这篇文章来回答一下. 在学习嵌入式Linux之前,肯定要有C语言基础.汇编基础有没有无所谓(就那么几条汇编指令,用到了一看就会). C语言要学 ...