美文网首页
call, apply 与 bind

call, apply 与 bind

作者: yuho_小豪哥 | 来源:发表于2019-11-04 10:29 被阅读0次

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 方法相同,也是函数上下文的对象,但是后面传入的是一个参数列表,而不是单个数组

示例

let obj = {
  age: 6
}

function func(name, favorite) {
  console.log(`${name} is ${this.age} years old and he likes ${favorite} very much.`)
}

func.apply(obj, ['Peter', 'football']) // Peter is 6 years old and he likes football very much.
func.call(obj, 'Jack', 'basketball') // Jack is 6 years old and he likes basketball very much.

对比可看到,两个方法出了传参方式有所不同,作用是一样。在实际开发中,如果你的参数本来就存在一个数组中(如 arguments,当然这只是类数组),那自然就用 apply,如果参数比较散乱相互之间没什么关联,就用 call。

bind 与 apply、call 的异同

  • bind() 方法是 ES5 中扩展的方法,并不兼容低版本的 IE 浏览器。
  • bind() 与 call() 有些类似,接收的参数有两部分,第一部分是作为函数上下文的对象,第二部分传入的是参数列表。
  • 但不同的是,bind() 返回的是一个改变了执行上下文 this 的函数,且不会立即执行,需要手动调用。
function func(a, b, c) {
    console.log(a, b, c);
}
let func1 = func.bind(null, 'test');

func('A', 'B', 'C');            // A B C
func1('A', 'B', 'C');           // test A B
func1('B', 'C');                // test B C
func.call(null, 'test');      // test undefined undefined

call 是把第二个及以后的参数作为 func 方法的实参传进去,而 func1 方法的实参实则是在 bind 中参数的基础上再往后排。

原生实现 bind() 方法

if (!Function.prototype.bind) {
  Function.prototype.bind = function () {
    var self = this,                        // 保存原函数
      context = [].shift.call(arguments), // 保存需要绑定的this上下文
      args = [].slice.call(arguments);    // 剩余的参数转为数组
    return function () {                    // 返回一个新函数
      self.apply(context,[].concat.call(args, [].slice.call(arguments)));
    }
  }
}

总结

三个方法相同点

  1. 都是用来改变函数的 this 对象的指向的
  2. 第一个参数都是 this 要指向的对象
  3. 都可以利用后续参数传参

三个方法不同点

  1. 三者的传参方式不同
  2. bind 的返回值是一个函数,需手动调用,而 apply 和 call 都是对函数的直接调用

参考文章

相关文章

网友评论

      本文标题:call, apply 与 bind

      本文链接:https://www.haomeiwen.com/subject/csvrbctx.html