引言

这是我的第一篇前端面试题文章,也是用来帮助自己巩固复习知识, 在之后希望拿到自己满意的offer,这第一篇讲的就是一道常见的面试题,关于JavaScript中apply、call、bind三者的用法及区别。

正文

如果有不想看过程的小伙伴可以直接跳到 总结

一、apply、call、bind的共同用法

先将一下特别概念性的,三者的共同用法就是可以改变函数的this指向,将函数绑定到上下文中。接下来看一个普通的应用场景:

let obj1 = {
my_favorite : 'banana',
add: function (fruit) {
console.log('我喜欢的水果是' + fruit + ',但是我最爱的水果是' + this.my_favorite)
}
} let obj2 = {
my_favorite: 'orange'
} obj1.add('apple')
//输出结果为: 我喜欢的水果是apple,但是我最爱的水果是banana

可以看到最后一行代码我们调用了obj1中的add函数,并传入了一个参数apple。add函数中的 this 指的是他所在的对象obj1,所以this.my_favorite 就是banana, 但是我们如果想获得obj2中的my_favorite, 该怎么办呢?接下来看一下每个函数的用法吧~

二、 apply

语法:fun.apply(obj,[arry])

  • 第一个参数: 传入的是this需要指向的对象
  • 第二个参数: 传入的是一个数组,作为 fun 函数的参数
let obj1 = {
my_favorite : 'banana',
add: function (...fruit) { //...fruit 表示的意思是可接收多个参数
console.log('我喜欢的水果是' + fruit + ',但是我最爱的水果是' + obj2.my_favorite)
}
} let obj2 = {
my_favorite: 'orange'
} obj1.add.apply(obj2, ['apple', 'Watermelon'])
//输出结果为:我喜欢的水果是apple,Watermelon,但是我最爱的水果是orange

obj1.add.apply(obj2, ['apple', 'Watermelon'])

这一行代码, 第一个参数将obj1中的add函数的 this 指向了obj2 , 第二个参数以数组形式传入多个参数,作为 obj1 中的 add 函数传入的参数, 所以最后能将 apple 和 watermelon 都输出。

三、 call

语法:fun.call(obj,[arg1, arg2, arg3...,argN]

  • 第一个参数: 传入的是this需要指向的对象
  • 其余参数: 除了第一个参数,其他的参数都是作为 fun 的传入参数

call 和 apply 唯一的区别就是在于给 fun 函数传入参数的形式不同, call是将多个参数逐个传入, apply 是 将多个参数放在一个数组中,一起传入

话不多说,直接来看看 call 的例子:

let obj1 = {
my_favorite : 'banana',
add: function (...fruit) {
console.log('我喜欢的水果是' + fruit + ',但是我最爱的水果是' + obj2.my_favorite)
}
} let obj2 = {
my_favorite: 'orange'
} obj1.add.call(obj2, 'apple', 'Watermelon')
//输出结果为:我喜欢的水果是apple,Watermelon,但是我最爱的水果是orange

大家可以对比一下 call 和 apply 的区别到底在哪里

四、 bind

语法:fun.bind(obj)(arg)

  • bind的第一个参数:传入的是this需要指向的对象
  • 因为函数bind返回的是一个函数,即将 fun 的 this 指向 obj 后不进行自身调用, 我们需要自己进行一次调用, 所以要在函数bind后面再加一个小括号进行自身调用, 而小括号里则可以输出传给 fun 函数的参数, 输入的可以是数组形式的,也可以是逐个传入的。

简单看一下例子:

let obj1 = {
my_favorite : 'banana',
add: function (...fruit) {
console.log('我喜欢的水果是' + fruit + ',但是我最爱的水果是' + obj2.my_favorite)
}
} let obj2 = {
my_favorite: 'orange'
} obj1.add.bind(obj2)('apple', 'Watermelon')
obj1.add.bind(obj2)(['apple', 'Watermelon'])
//输出结果为:我喜欢的水果是apple,Watermelon,但是我最爱的水果是orange
//输出结果为:我喜欢的水果是apple,Watermelon,但是我最爱的水果是orange

可以很清楚的看到, bind 有点类似 apply 和 call 的结合,只不过它返回的是一个函数,需要自己进行一下调用, 而传给 fun 函数的参数形式可以是像 apply 一样的数组形式, 也可以是像 call 一样的逐个传入的形式。

五、其他应用场景

  • 获取一个数组中的最大值或最小值
/* 普通情况,我们是这样获取数组中的最大值、最小值的 */

let max = Math.max(22, 33, 54, 88, 35, 44, 78, 80)
let min = Math.min(22, 33, 54, 88, 35, 44, 78, 80)
console.log(max, min)
//88 22

有没有感觉特别的麻烦,那接下来看看使用了这几个函数之后是什么样子的吧

/* 使用函数apply */
let arr = [22, 33, 54, 88, 35, 44, 78, 80]
let max = Math.max.apply(null, arr)
let min = Math.min.apply(null, arr)
console.log(max, min)
//88 22

这样看着是不是特别的简洁,因为我们不需要把arr 中的数组一个个传入进行比较,而是直接以数组形式传入就可以了。

六、总结

  1. apply、call、bind 三者都是可以改变函数的this指向的
  2. apply 和 call 都是改变函数this指向,并传入参数后立即调用执行该函数
  3. bind 是在改变函数this指向,并传入参数后返回一个新的函数,不会立即调用执行
  4. apply 传入的参数是数组形式的;call 传入的参数是按顺序的逐个传入并以逗号隔开; bind 传入的参数既可以是数组形式,也可以是按顺序逐个传入。

结束语

apply、call、bind三者的用法及区别是经常考到的一道面试题,希望对大家有所帮助。之后我还会每天更新一个前端面试题,来帮助大家以及我自己巩固知识点,喜欢的小伙伴可以点个关注, 希望你们都拿到自己满意的offer

一个简单的例子让你很轻松地明白JavaScript中apply、call、bind三者的用法及区别的更多相关文章

  1. 用一个简单的例子来理解python高阶函数

    ============================ 用一个简单的例子来理解python高阶函数 ============================ 最近在用mailx发送邮件, 写法大致如 ...

  2. Spring-Context之一:一个简单的例子

    很久之前就想系统的学习和掌握Spring框架,但是拖了很久都没有行动.现在趁着在外出差杂事不多,就花时间来由浅入深的研究下Spring框架.Spring框架这几年来已经发展成为一个巨无霸产品.从最初的 ...

  3. 关于apriori算法的一个简单的例子

    apriori算法是关联规则挖掘中很基础也很经典的一个算法,我认为很多教程出现大堆的公式不是很适合一个初学者理解.因此,本文列举一个简单的例子来演示下apriori算法的整个步骤. 下面这个表格是代表 ...

  4. 跨站脚本功攻击,xss,一个简单的例子让你知道什么是xss攻击

    跨站脚本功攻击,xss,一个简单的例子让你知道什么是xss攻击 一.总结 一句话总结:比如用户留言功能,用户留言中写的是网页可执行代码,例如js代码,然后这段代码在可看到这段留言的不同一户的显示上就会 ...

  5. 从一个简单的例子谈谈package与import机制

    转,原文:http://annie09.iteye.com/blog/469997 http://blog.csdn.net/gdsy/article/details/398072 这两篇我也不知道到 ...

  6. 扩展Python模块系列(二)----一个简单的例子

    本节使用一个简单的例子引出Python C/C++ API的详细使用方法.针对的是CPython的解释器. 目标:创建一个Python内建模块test,提供一个功能函数distance, 计算空间中两 ...

  7. fitnesse - 一个简单的例子(slim)

    fitnesse - 一个简单的例子(slim) 2017-09-30 目录1 编写测试代码(Fixture code)2 编写wiki page并运行  2.1 新建wikiPage  2.2 运行 ...

  8. Struts2的配置和一个简单的例子

    Struts2的配置和一个简单的例子 笔记仓库:https://github.com/nnngu/LearningNotes 简介 这篇文章主要讲如何在 IntelliJ IDEA 中使用 Strut ...

  9. 一个简单的例子搞懂ES6之Promise

    ES5中实现异步的常见方式不外乎以下几种: 1. 回调函数 2. 事件驱动 2. 自定义事件(根本上原理同事件驱动相同) 而ES6中的Promise的出现就使得异步变得非常简单.promise中的异步 ...

随机推荐

  1. 干货分享丨玩转物联网IoTDA服务系列四-智能网关

    摘要:该场景主要描述的是设备可以通过MQTT协议与物联网平台进行交互,用户可以在控制台产品详情中自定义Topic,通过应用侧接口或控制台创建数据转发规则,把设备上报的消息转发给其他华为云服务,供应用侧 ...

  2. 用友U8API 8.9-15.0接口开发前提,选好开发方式

    在用友接口开发这条路上,走走停停过了好几年.对于如何选择哪种方式,目前总结几点, 对于开发,目前可以实现的有三种方式       一.是通过用友官方提供的(EAI/API)接口     这种方式的优点 ...

  3. STL set

    写在前面:STL大法好! 容器set,可以实现排序,插入元素不能重复(所以可能插入失败) 接下来我们看一下set的基本用法 begin()     返回set容器的第一个元素的地址 end() 返回s ...

  4. SpringBoot环境下使用测试类注入Mapper接口报错解决

    当我们在进行开发中难免会要用到测试类,而且测试类要注入Mapper接口,如果测试运行的时候包空指针异常,看看测试类上面的注解是否用对! 正常测试我们需要用到的注解有这些: @SpringBootTes ...

  5. pandas属性和方法

    Series对象的常用属性和方法 loc[ ]和iloc[ ]格式示例表 Pandas提供的数据整理方法 Pandas分组对象的属性和方法 date_range函数的常用freq参数表

  6. 6.6 省选模拟赛 线段 二维数点问题 树套树 CDQ分治

    LINK:线段 还是太菜了 没看出这道题真正的模型 我真是一个典型的没脑子选手. 考虑如何查询答案. 每次在一个线段x的状态被更改后 可以发现有影响的是 和x相连那段极长连续1子段. 设这个子段左端点 ...

  7. rabbitMQ安装问题记录

    参考链接: rabbitmq国内镜像地址:https://www.newbe.pro/Mirrors/Mirrors-RabbitMQ/ https://www.zhihu.com/question/ ...

  8. x86架构:保护模式下利用中断实现抢占式多任务运行

         站在用户角度考虑,一个合格的操作系统即使在单核下也能 "同时" 执行多个任务,这就要求CPU以非常快的频率在不同任务之间切换,让普通人根本感觉不到任务的切换.windwo ...

  9. NameNode中的高可用方案

    NN中元数据的可靠性是可以保证的,但是其可用性并不高,因为Namenode是单节点的,所以一旦这个节点不能工作,那么整个hdfs都不能工作,但是由于SecondaryNameNode的机制,所以,即便 ...

  10. Linux下运行windows 系统下编辑的Python脚本显示“: 没有那个文件或目录”的过程及解决方案

    今天在 linux 系统下执行一windows下编辑的python脚本,提示(:没有那个文件或目录)英文提示:(:No such file of directory)如下: 查看文件的权限发现并没有问 ...