首先,在使用call,apply,bind方法时,我们有必要知道这三个方法究竟是来自哪里?为什么可以使用的到这三个方法?
console.log(Function.prototype.hasOwnProperty('call')) //trueconsole.log(Function.prototype.hasOwnProperty('apply')) //trueconsole.log(Function.prototype.hasOwnProperty('bind')) //true
上面代码中,都返回了true,表明三种方法都是继承自Function.prototype的。当然,普通的对象,函数,数组都继承了Function.prototype对象中的三个方法,所以这三个方法都可以在对象,数组,函数中使用。三个方法的作用都是一样的,简单来说就是改变当前使用该方法的对象中的this指向。
我感觉用大白话来说就是, A有的东西你没有,但是你想跟A借用,怎么去借?我感觉这个就是最最最通俗易懂的解释了。
举个栗子吧:
有2个人steven和becky,他们都有name和phoneBattery,不同的是steven有一个charge的方法(充电宝),可以给给手机充电
<script> const steven = { name: 'Steven', phoneBattery: 70, // 手机电池剩余时间 charge: function (level) { this.phoneBattery = level } } const becky = { name: 'Becky', phoneBattery: 30, // 手机电池剩余时间 }</script>
我们先给steven充电至100
const steven = { name: 'Steven', phoneBattery: 70, charge: function (level) { this.phoneBattery = level } } console.log(steven) steven.charge(100) console.log(steven)

那么,becky 的手机也没电,想去跟steven借用一下充电宝(也就是借用charge方法)咋整呢? steven.charge.call(becky, 90)
const steven = { name: 'Steven', phoneBattery: 70, charge: function (level) { this.phoneBattery = level } } const becky = { name: 'Becky', phoneBattery: 30, } console.log(becky) steven.charge.call(becky, 90) // ***********重要代码 console.log(becky)

很神奇发现有没有?becky里面根本就没有charge方法啊,他是怎么就给手机调用到了steven里面的方法了呢?大家也看到了我这边用了个call,call改变了执行环境。
那么call和apply又有什么不同呢?我们先给charge增加2个参数
call写法,其实与call差不多,传参形式不一样。call传入的是参数若干个列表
<script> const steven = { name: 'Steven', phoneBattery: 70, // 手机电池剩余时间 charge: function (level1, level2) { this.phoneBattery = level1 + level2 } } const becky = { name: 'Becky', phoneBattery: 30, // 手机剩余时间 } console.log(becky) steven.charge.call(becky, 30, 40) console.log(becky);</script>
2.apply写法,其实是与call差不多的,只是传参形式不一样。apply传入的是包含多个参数的数组

3.bind写法
bind创建了一个新函数,必须手动去调用

总结一下:
apply和call基本类似,他们的区别只是传入的参数不同。
apply传入的参数是包含多个参数的数组
call传入的参数是若干个参数列表
bind方法会创建一个新的函数,当被调用的时候,将其this关键字设置为提供的值,我们必须手动去调用