博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
call/apply/bind作用和区别
阅读量:4130 次
发布时间:2019-05-25

本文共 2620 字,大约阅读时间需要 8 分钟。

答案:

他们都可以改变函数的作用域。

  • call/apply 可以直接执行该函数,而 bind 不会立刻执行

fucntion.bind(thisArg, arg1, arg2, ...)
  • call/apply 作用类似,都可以改变指针和执行函数,区别在于传参不同,call 需要单个传参,apply 通过数组传参

function.call(thisArg, arg1, arg2, ...)function.apply(thisArg, [arg1, arg2, ...])

 

详细解析:

this代表函数(方法)执行的上下文环境,但在 JavaScript 中 this 不是固定不变的,它会随着执行环境的改变而改变。

  • 1.在方法中,this 表示该方法所属的对象。
  • 2.如果单独使用,this 表示全局对象。
  • 3.在函数中,this 表示全局对象。
  • 4.在函数中,在严格模式下,this 是未定义的(undefined)。
  • 5.在事件中,this 表示接收事件的元素。
  • 6.类似 call() 和 apply() 方法可以将 this 引用到任何对象。

JavaScript 提供了call、apply、bind这三个方法,来切换/固定this的指向。

call和apply

call 和 aplly 作用完全一样,都是在特定的上下文中调用函数,或者说改变函数内部的this指向;区别仅在于接收参数的方式不同。

function add(a, b) {  return a + b;} function sub(a, b) {  return a - b;} console.log(add.call(sub, 2, 1));//3

为什么add.call(sub, 2, 1)的执行结果是3呢,因为call()方法改变了this的指向,使得sub可以调用add的方法,也就是用sub去执行add中的内容。

var dog = {  name: "dog"};var cat = {  name: "cat"};var sayName = function (age, gender) {  console.log(this.name + "," + age + "," + gender)};sayName(); //undefinedsayName.call(dog, 2, "male"); //dog,2,malesayName.call(cat, 3, "female"); //cat,3,femalesayName.apply(dog, [2, "male"]); //dog,2,malesayName.apply(cat, [3, "female"]); //cat,3,female

我们在全局环境定义了一个 sayName 方法,调用该方法时会将当前环境的 name 属性 (this.name) 显示到控制台上。当我们在全局环境调用 sayName() 时,由于全局环境并没有 this.name 属性,因此显示了 undefined。

使用 call 或者 apply,就可以改变函数的执行环境,或者说改变函数内部的 this 指向。例如 sayName.call(dog),表示将sayName 内部的 this 指向了 dog 对象,因此 this.name 显示为 "dog"。当我们调用sayName.call(cat)时,sayName 内部的 this 又指向了 cat 对象。总结一句话就是call()可以让括号里的对象来继承括号外函数的属性。

可以看出来,call与apply的作用完全相同,区别仅在于接收参数的方式不同。

fn.call(context, arg1, arg2, ...)fn.apply(context, [arg1, arg2, ...])

call 和 apply 接收的第一个参数都是函数的运行环境。使用 call 时传递给函数的参数必须逐个传入,而使用 apply 时函数的参数应该是一个数组,或者类数组对象(如 arguments 对象)。至于使用 call 还是 apply,完全取决于采用哪种方法给函数传递参数更方便。在不需要给函数传递参数的情况下,使用哪个方法都无所谓。

apply的2种写法:

People.apply(this, [name, age]);People.apply(this, arguments);

在这里arguments和[name, age]是等价的。

 

bind

bind 与前两者作用类似,都是改变函数内部的 this 指向,区别在于 bind 会创建一个新的函数实例,每次调用该实例时,都会在被绑定的环境中运行。简单来说就是,bind方法返回一个新函数,以后调用了才会执行,但apply、call会立即执行。

function f(y, z){  return this.x + y + z;}var m = f.bind({x : 1}, 2);console.log(m(3));//6

这里bind方法会把它的第一个实参绑定给f函数体内的this,所以这里的this即指向{x : 1}对象,从第二个参数起,会依次传递给原始函数,这里的第二个参数2,即是f函数的y参数,最后调用m(3)的时候,这里的3便是最后一个参数z了,所以执行结果为1 + 2 + 3 = 6分步处理参数的过程其实是一个典型的函数柯里化的过程(Curry)。

var dog = {  name: "dog"};var cat = {  name: "cat"};var sayName = (function (age, gender) {  console.log(this.name + "," + age + "," + gender)}).bind(dog, 3, "male");sayName.call(cat, 2, "female"); //dog,3,male

我们创建 sayName 函数时,使用 bind 将该函数的 this 指向了 dog 对象,同时还绑定了传入函数的参数。

现在我们调用 sayName.call(cat, 2, "female"),发现不论是this对象,还是传入函数的参数,都是之前被绑定的值了。

转载地址:http://xjuvi.baihongyu.com/

你可能感兴趣的文章
tp5封装通用的修改某列值
查看>>
laravel控制器与模型名称不统一
查看>>
vue登录拦截
查看>>
npm配置淘宝镜像仓库以及electron镜像
查看>>
linux设置开机自启动脚本的最佳方式
查看>>
VUE SPA 单页面应用 微信oauth网页授权
查看>>
phpstorm 集成 xdebug 进行调试
查看>>
npm和node升级的正确方式
查看>>
laravel事务
查看>>
springcloud 连续请求 500
查看>>
vue复用新增和编辑表单
查看>>
Ubuntu 16.04 apt-get更换为国内阿里云源
查看>>
laravel部署到宝塔步骤
查看>>
小程序获取access_token
查看>>
navicat远程连接mysql数据库
查看>>
tp5令牌数据无效 解决方法
查看>>
自己的网站与UCenter整合(大致流程)
查看>>
laravel 制作通用的curd 后台操作
查看>>
【小红书2017年笔试】求一个数组中平均数最大的子数组
查看>>
Linux基础系列-定时器与时间管理
查看>>