一个简单的例子让你轻松地明白JavaScript中apply、call、bind三者的用法及区别

简介: 这篇文章也算是讲解了前端面试 常考的知识点 ,即关于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指向的


              1. apply 和 call 都是改变函数this指向,并传入参数后立即调用执行该函数


              1. bind 是在改变函数this指向,并传入参数后返回一个新的函数,不会立即调用执行


              1. apply 传入的参数是数组形式的;call 传入的参数是按顺序的逐个传入并以逗号隔开;bind 传入的参数既可以是数组形式,也可以是按顺序逐个传入。


              apply、call、bind三者的用法及区别是经常考到的一道面试题,希望对大家有所帮助。喜欢的小伙伴可以点个关注, 希望你们都拿到自己满意的offer

              相关文章
              |
              1月前
              |
              JavaScript 前端开发
              js中的bind,call,apply方法的区别以及用法
              JavaScript中,`bind`、`call`和`apply`均可改变函数的`this`指向并传递参数。其中,`bind`返回一个新函数,不立即执行;`call`和`apply`则立即执行,且`apply`的参数以数组形式传递。三者在改变`this`指向及传参上功能相似,但在执行时机和参数传递方式上有所区别。
              28 1
              |
              1月前
              |
              JavaScript 前端开发
              JS中的构造函数的含义和用法
              构造函数是JavaScript中用于创建新对象的特殊函数,通常首字母大写。通过`new`关键字调用构造函数,可以初始化具有相同属性和方法的对象实例,从而实现代码复用。例如,定义一个`Person`构造函数,可以通过传入不同的参数创建多个`Person`对象,每个对象都有自己的属性值。此外,构造函数还可以包含方法,使每个实例都能执行特定的操作。构造函数的静态属性仅能通过构造函数本身访问。ES6引入了`class`语法糖,简化了类的定义和实例化过程。
              31 1
              |
              2月前
              |
              JavaScript 前端开发
              JS高级—call(),apply(),bind()
              【10月更文挑战第17天】call()`、`apply()`和`bind()`是 JavaScript 中非常重要的工具,它们为我们提供了灵活控制函数执行和`this`指向的能力。通过合理运用这些方法,可以实现更复杂的编程逻辑和功能,提升代码的质量和可维护性。你在实际开发中可以根据具体需求,选择合适的方法来满足业务需求,并不断探索它们的更多应用场景。
              14 1
              |
              2月前
              |
              JavaScript 前端开发
              JS try catch用法:异常处理
              【10月更文挑战第12天】try/catch` 是 JavaScript 中非常重要的一个特性,它可以帮助我们更好地处理程序中的异常情况,提高程序的可靠性和稳定性。
              35 1
              |
              1月前
              |
              JavaScript 前端开发
              JavaScript中的原型 保姆级文章一文搞懂
              本文详细解析了JavaScript中的原型概念,从构造函数、原型对象、`__proto__`属性、`constructor`属性到原型链,层层递进地解释了JavaScript如何通过原型实现继承机制。适合初学者深入理解JS面向对象编程的核心原理。
              30 1
              JavaScript中的原型 保姆级文章一文搞懂
              |
              5月前
              |
              JavaScript Java 测试技术
              基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
              基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
              109 2
              |
              1月前
              JS+CSS3文章内容背景黑白切换源码
              JS+CSS3文章内容背景黑白切换源码是一款基于JS+CSS3制作的简单网页文章文字内容背景颜色黑白切换效果。
              21 0
              |
              5月前
              |
              JavaScript Java 测试技术
              基于springboot+vue.js+uniapp的小区物流配送系统附带文章源码部署视频讲解等
              基于springboot+vue.js+uniapp的小区物流配送系统附带文章源码部署视频讲解等
              155 4
              |
              5月前
              |
              JavaScript Java 测试技术
              基于springboot+vue.js+uniapp的宠物援助平台附带文章源码部署视频讲解等
              基于springboot+vue.js+uniapp的宠物援助平台附带文章源码部署视频讲解等
              90 4