JavaScript 高级程序设计(第 3 版)中是这样介绍的:
There are two additional methods for functions: apply() and call(). These methods both call the function with a specific this value, effectively setting the value of the this object inside the function body.
ECMAScript5 defines an additional method called bind(). The bind() method creates a new function instance whose this value is bound to the value that was passed into bind().
每个函数都包含两个非继承而来的方法:apply() 和 call()。这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内 this 对象的值。
ECMAScript5 还定义了一个方法:bind()。这个方法会创建一个函数的实例,其 this 值会被绑定到传给 bind() 函数的值。
apply 与 call 的异同
相似处
作用一模一样,都是改变函数运行时的 this 指向。
不同处
主要区别在于传参的形式:
- apply 方法传入两个参数:作为函数上下文的对象,以及函数参数所组成的数组
- call 方法传入的第一个参数与 apply 方法相同,也是函数上下文的对象,但是后面传入的是一个参数列表,而不是单个数组
示例
1 | let obj = { |
对比可看到,两个方法出了传参方式有所不同,作用是一样。在实际开发中,如果你的参数本来就存在一个数组中(如 arguments,当然这只是类数组),那自然就用 apply,如果参数比较散乱相互之间没什么关联,就用 call。
bind 与 apply、call 的异同
- bind() 方法是 ES5 中扩展的方法,并不兼容低版本的 IE 浏览器。
- bind() 与 call() 有些类似,接收的参数有两部分,第一部分是作为函数上下文的对象,第二部分传入的是参数列表。
- 但不同的是,bind() 返回的是一个改变了执行上下文 this 的函数,且不会立即执行,需要手动调用。
1 | function func(a, b, c) { |
call 是把第二个及以后的参数作为 func 方法的实参传进去,而 func1 方法的实参实则是在 bind 中参数的基础上再往后排。
原生实现 bind() 方法
1 | if (!Function.prototype.bind) { |
总结
三个方法相同点
- 都是用来改变函数的 this 对象的指向的
- 第一个参数都是 this 要指向的对象
- 都可以利用后续参数传参
三个方法不同点
- 三者的传参方式不同
- bind 的返回值是一个函数,需手动调用,而 apply 和 call 都是对函数的直接调用