浅解析JS中的 call、apply、bind

call、apply、bind 是 Function对象中的三个方法,这三个方法的主要作用是改变 this 的指向,也就是改变执行上下文的指向。首先看一段代码

call(this.Args,[,args...])

let member = {
  name: 'super man',
  age: 1001,
  introduce: function () {
      console.log("Hello I'm " + this.name);
  }
}

function otherFunc(param) {
  console.log('param is : ' + param);
  console.log('name : ' + this.name);
  console.log('age : ' + this.age);
  this.introduce();
}
otherFunc.call(member, 'test')

打印结果如下

param is : test
name : super man
age : 1001
Hello I'm super man

发生了什么?otherFunc.call() 参数中把我们定义的member传入了,然后函数内改变了this的指向,将this指向meber 所以otherFunc函数内没有定义的属性 name,age,和方法 introduce(),都可以调用。这是不是就贴合了继承的特点

apply(thisArgs,[,args[]])

function otherFunc(param1,param2) {
  console.log('param1 is : ' + param1);
  console.log('param2 is : ' + param2);
  console.log('name : ' + this.name);
  console.log('age : ' + this.age);
  this.interduce();
}
otherFunc.apply(member,['test','func']);

otherFunc改成了两个参数,call 换成 apply。打印结果如下

param1 is : test
param2 is : func
name : super man
age : 1001
Hello I'm super man

根据上面的代码发现apply同样改变了this的指向,而call 和apply的直观差别在于参数,call传入的是参数列表,而apply传入的是数组,而且在函数中取参的时候却是以参数列表的形式对应的。

call 和 apply 还有一点相同的地方,调用时会立即执行函数,如上面的interduce(),如果我们想先改变this指向而不立即执行该怎么处理,这时候就要使用bind了。

bind(thisArgs,[,agrs...])

let bindFunc = otherFunc.bind(member,'test','func');
bindFunc();

bind() 会返回一个新的函数,this指向第一个参数,而其余参数将作为新函数的参数。

上面的写法

let bindFunc = otherFunc.bind(member);
bindFunc('test','func');//参数后传
bindFunc('test1','func2');//新参数

总结:call、apply、bind 都改变了执行上下文的指向,参数不同,call 和 bind 以参数列表形式传参数,apply 传数组,call、apply会立即执行函数,而bind会返回一个新函数,手动调用。

未经允许不得转载