先分析下3个方法的作用
改变this的指向。
传入参数。
call apply返回函数结果, bind 返回新函数
一、call方法的实现
改变this指向
首先我们知道,对象上的方法,在调用时,this是指向对象的。
![img_672728664bb3d24fa066f9f950741af6.png](https://i-blog.csdnimg.cn/blog_migrate/f5640aa8ecd9fe150784a25fc69c472c.png)
知道了这一点我们就可以实现改变this的指向
![img_6e0aad6c28b1e07bd096ecb231ee7d49.png](https://i-blog.csdnimg.cn/blog_migrate/665a959d1d1f6cc81761240e1445fc1f.png)
测试
![img_ffcf7b921852687297a27d35c1d026c3.png](https://i-blog.csdnimg.cn/blog_migrate/0eec549390d2a29eed57aa9ab6c3af4d.png)
现在,改变this的值,实现了
最简单实现es6
![img_7a223ea1fc97aaa3be6b13519a5fe1c4.png](https://i-blog.csdnimg.cn/blog_migrate/90fcf33ac21d584e5c97c369080d8f20.png)
二、apply方法的实现
其实apply和call差不多,没什么大区别
利用已经写好的myCall来实现
![img_a440ca7003a039299528e3a34c3a2869.png](https://i-blog.csdnimg.cn/blog_migrate/dc0856b39bebaebaf04f297e4a8711cf.png)
不用myCall
![img_7abe7954cf5f882256c227c385ae4abe.png](https://i-blog.csdnimg.cn/blog_migrate/2d09bbf96d8b01c8851cb3c782b77e1a.png)
测试
![img_7115ee524d4fe69c4deba076fa565cfc.png](https://i-blog.csdnimg.cn/blog_migrate/929d1e1bf7943362228b2cff74c2e8b0.png)
效果没区别
三、bind方法的实现(利用call方法实现)
首先我们可以通过给目标函数指定作用域来简单实现bind()方法:
![img_3c8096b8c58758177e32183d841ac555.png](https://i-blog.csdnimg.cn/blog_migrate/af2fe2203e389113a4b9715a8b316613.png)
考虑到函数柯里化的情况,我们可以构建一个更加健壮的bind():
![img_775f20524b4c595f9fda9cd00fe760f9.png](https://i-blog.csdnimg.cn/blog_migrate/0243b054114dfb73d09050ac4771e50b.png)
这次的bind()方法可以绑定对象,也支持在绑定的时候传参。
继续,Javascript的函数还可以作为构造函数,那么绑定后的函数用这种方式调用时,情况就比较微妙了,需要涉及到原型链的传递:
![img_66732ad501eb147d39f23697c0531fcb.png](https://i-blog.csdnimg.cn/blog_migrate/34f841fd362ee5f13acbe0206b4807cd.png)
这是《JavaScript Web Application》一书中对bind()的实现:通过设置一个中转构造函数F,使绑定后的函数与调用bind()的函数处于同一原型链上,用new操作符调用绑定后的函数,返回的对象也能正常使用instanceof,因此这是最严谨的bind()实现。
对于为了在浏览器中能支持bind()函数,只需要对上述函数稍微修改即可:
![img_eb04b1503a3f9221152bd45db919dbcd.png](https://i-blog.csdnimg.cn/blog_migrate/6c4bdc613e29b724fa03be17739129e3.png)
![img_83a21cd0b4843eeba48365fa98042b30.png](https://i-blog.csdnimg.cn/blog_migrate/47c951324c9d0db8cab3fb674d4dcde7.png)
四、模拟代码
模拟call
![img_fbad936f5cd5bf63964dac8e222df5b6.png](https://i-blog.csdnimg.cn/blog_migrate/3a6f0d24393de5973853b1855cf8cdb6.png)
模拟apply
![img_183b4bc809e605f5ac1249910e28d178.png](https://i-blog.csdnimg.cn/blog_migrate/489ee70651fe307bc8507c01602fa4d1.png)
模拟bind
![img_81da298741d40aca936c5fcf5a9d2f18.png](https://i-blog.csdnimg.cn/blog_migrate/f9550d1ed37ef46b752ea7b98d1c74eb.png)