js中call、bind、apply你知多少?

栏目: JavaScript · 发布时间: 5年前

内容简介:@在我们日常开发过程中call、bind、apply无疑是我们用的比较多的语法,今天在开发中看到有同事傻傻分不清call和bind的区别,故在解释一通之后,写下此文;从MDN 文档 call我们可以了解到: call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。

@ TOC

在我们日常开发过程中call、bind、apply无疑是我们用的比较多的语法,今天在开发中看到有同事傻傻分不清call和bind的区别,故在解释一通之后,写下此文;

首先查看文档理解含义

call()

从MDN 文档 call我们可以了解到: call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。

  • fun.call(thisArg, arg1, arg2, ...)
  • thisArg 在 fun 函数运行时指定的 this 值*。*需要注意的是,指定的 this 值并不一定是该函数执行时真正的 this 值,如果这个函数在 非严格模式 下运行,则指定为 null undefined this 值会自动指向全局对象(浏览器中就是 window 对象),同时值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的自动包装对象。(ps:严格模式下 我们对函数的的调用必须严格的写出被调用的函数的对象);
  • arg1, arg2, ... 指定的参数列表

先举个例子:

// main.js
  const foo={
      name:'foo',
      getFoo(...args){
        console.log('this===',this,'this.name==',this.name)
        console.log('-----------------------------------')
        console.log('...args=====',...args)
      }
    }
    const bar={
      name:'bar',
      getBar(...args){
        console.log('this===',this,'this.name==',this.name)
        console.log('-----------------------------------')
        console.log('...args=====',...args)
      }
    }
    foo.getFoo() //this=== {name: "foo", getFoo: ƒ} this.name== foo  ----------------------------------- ...args=====
    bar.getBar() //this=== {name: "bar", getBar: ƒ} this.name== bar  ----------------------------------- ...args=====

复制代码

假如我们想在getFoo去借bar里面的东西用用,该怎么办呢? 也许有同学想到的是这样:

foo.getFoo(bar.name) // this=== {name: "foo", getFoo: ƒ} this.name== foo -----------------------------------  ...args===== bar

复制代码

毫无疑问,这是没问题的,但此时只是正常的传参,能否干脆点把this.name也改成bar呢;根据call的定义:

foo.getFoo.call(bar,'测试传参','测试call') //his=== {name: "bar", getBar: ƒ} this.name== bar ----------------------------------- ...args===== 测试传参 测试call
//使用call后,我们可以看到foo.getFoo的this此时指向了bar对象,此时的name拿到的bar的对象的name;
复制代码

apply()

从MDN 文档 apply我们可以了解到: apply() 方法调用一个具有给定 this 值的函数,以及作为一个数组(或类似数组对象)提供的参数。

  • func.apply(thisArg, [argsArray])

  • thisArg:可选的。在 func 函数运行时使用的 this 值。请注意, this 可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为 nullundefined 时会自动替换为指向全局对象,原始值会被包装。

  • argsArray:可选的。一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 func 函数。如果该参数的值为 null undefined ,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。浏览器兼容性 请参阅本文底部内容。

继续使用刚才的foo和bar

foo.getFoo.apply(bar,['测试传参','测试apply']) //his=== {name: "bar", getBar: ƒ} this.name== bar ----------------------------------- ...args===== 测试传参 测试apply

复制代码

总结 call方法和apply方法两者极度相似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组。

bind()

从MDN 文档 bind我们可以了解到:

bind()方法创建一个新的函数,在调用时设置this关键字为提供的值。并在调用新函数时,将给定参数列表作为原函数的参数序列的前若干项。

  • function.bind(thisArg[, arg1[, arg2[, ...]]])

  • thisArg 调用绑定函数时作为 this 参数传递给目标函数的值。 如果使用 new 运算符构造绑定函数,则忽略该值。当使用 bindsetTimeout 中创建一个函数(作为回调提供)时,作为 thisArg 传递的任何原始值都将转换为 object 。如果 bind 函数的参数列表为空,执行作用域的 this 将被视为新函数的 thisArg

  • arg1, arg2, ... 当目标函数被调用时,预先添加到绑定函数的参数列表中的参数。

emmmm...继续最最上面的那个foo和bar

foo.getFoo.bind(bar,'测试传参','测试bind') // 此时是无输出,因为bind()方法创建一个新的函数,当前函数并没有执行


复制代码

修改如下:

const foobindbar = foo.getFoo.bind(bar,'测试传参','测试bind');

console.log(foobindbar)
    // ƒ getFoo(...args){
    //   console.log('this===',this,'this.name==',this.name)
    //   console.log('-----------------------------------')
    //   console.log('...args=====',...args)
    // }

foobindbar() //this=== {name: "bar", getBar: ƒ} this.name== bar ----------------------------------- ...args===== 测试传参 测试apply


复制代码

总结

call和apply的区别

call方法和apply方法两者极度相似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组。用apply时,即使传入的参数只有一个,也必须定义为数组才行;

call与apply 和 bind的区别

call与apply改变this的指向时,会直接触发函数;而bind会创建一个新的函数,在调用时设置this关键字为提供的值,使用bind时,会优先使用bind绑定的几个值; 如下:

foo.getFoo.bind(bar,'测试传参','测试bind')
const foobindbar = foo.getFoo.bind(bar,'测试传参','测试bind');

console.log(foobindbar)
    // ƒ getFoo(...args){
    //   console.log('this===',this,'this.name==',this.name)
    //   console.log('-----------------------------------')
    //   console.log('...args=====',...args)
    // }

foobindbar('参数1', '参数2') //this=== {name: "bar", getBar: ƒ} this.name== bar ----------------------------------- ...args=====  测试传参 测试apply 参数1 参数2
// ...args=====  测试传参 测试apply 参数1 参数2

复制代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Machine Learning in Action

Machine Learning in Action

Peter Harrington / Manning Publications / 2012-4-19 / GBP 29.99

It's been said that data is the new "dirt"—the raw material from which and on which you build the structures of the modern world. And like dirt, data can seem like a limitless, undifferentiated mass. ......一起来看看 《Machine Learning in Action》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

html转js在线工具
html转js在线工具

html转js在线工具