虽然我之前写过浅析 javascript 的 call 和 apply 方法,现在看来,对 call 和 apply 的理解并不深刻,故重新理解 call、apply 和 bind.
call 和 apply
call 和 apply 的用法这里就不再赘述,前面的文章已经讲过.而 call 和 apply 只是调用方法的不同,其他可以说是基本一致.下面看看 call 和 apply 的作用:
1、 改变 this 指向
2、 借用别的对象的方法
3、 调用函数(call 和 apply 方法都会使函数立即执行)
call 和 bind 的区别
bind 的用法详见Function.prototype.bind() ,这里只是一个简单示例:
1 | let obj = { |
通过这个示例可以得出 call 和 call 的区别
1、 bind 方法不会立即执行,而是返回一个改变了上下文 this 后的函数
2、 call 是把第二个及以后的参数实参传入,而 bind 返回的函数中是将实参直接传入
怎么实现
在我接触 js 的时候就已经是 es5 了,es5 已经实现了 bind 方法,但更多的时候需要我们去理解,以及实现的方法.大概思路是在 Function 的原型上添加 bind 方法,然后在 bind 方法内部用 call 和 apply 来绑定 this 的指向.
看下面这段代码(摘自:JavaScript 中 apply 、call 的详解):
1 | if (!Function.prototype.bind) { |
上面这段代码看起来没什么大不了的,但是细细体会的化,这段代码很有灵性.
[].shift、[].slice
咋一看,有点陌生呢, 可以理解为(new Array()).shift
=>[].shift
,那么这些数组方法都是继承于Array.prototype
的,所以在控制台中打印Array.prototype.shift === [].shift
的值为 true.
所以也可以理解为只是调用方式不同,一个是通过原型的方式直接在类上调用;一个是通过实例化,继承过来,然后再调用.这个两中调用方式的区别就很明了了,他们的 this 指向不同,在 [].slice 中,this 指向的是该实例 [],而在 Array.prototype.slice 中,this 指向的是 Array.prototype.而且从理论上来说,Array.prototype 的效率更高一下,毕竟少了一次实例化的过程.
那 arguments 为什么要通过 call 和 apply 使用数组的方法呢,因为 arguments 是一个伪数组对象.
相信看了这段有灵性的代码,上面的代码就不难理解了.虽然面试不会在问怎么实现一个 bind 方法,以及一些古老的方法了,但学习理解这些巧妙的、优雅的、有灵性的代码,才能加深我们对基础知识的理解,在将来才能更上一层楼.
参考文章:JavaScript 中 apply 、call 的详解
参考文章:js 中自己实现 bind 函数的方式
[越努力,越幸运!]