美文网首页
手写bind,apply,call方法

手写bind,apply,call方法

作者: Angel_6c4e | 来源:发表于2021-03-27 00:31 被阅读0次
三者区别:
  • call 和 apply 都是为了解决改变 this 的指向。作用都是相同的,只是传参的方式不同。
  • 除了第一个参数外,call 可以接收一个参数列表,apply 只接受一个参数数组。
  • bind不会立即调用,其他两个会立即调用。
// 使用
let developer = {
  parent: function (a,b){
    console.log(a,b)
   console.log(this.name)
  }
}
let obj={
 name:'张三'
}
developer.parent.call(obj,1,2)  // 1 2 张三
developer.parent.apply(obj,[1,2])  //arguments[1]  // 1 2 张三
developer.parent.bind(obj)(1,2)  //arguments[1]  // 1 2 张三
call的简易模拟实现(es6)
  • 思路
  1. 函数定义在哪里 :
    call是可以被所有方法调用的,所以毫无疑问的定义在 Function的原型上!
  2. 函数接收参数 :
    绑定函数被调用时只传入第二个参数及之后的参数。
    例如:Parent.call(this,1,2,3)
  3. 如何显式绑定this ?
    如果调用者是函数,被某一个对象所拥有,那么该函数在调用时,内部的this指向该对象。
Function.prototype.myCall= function (context = window) {
  // let cxt = context || window;
  // context为调用的上下文,this此处为函数,将这个函数作为context的方法
  context.fun = this;
  // 获取实参:返回一个数组[]
  let args = Array.from(arguments).slice(1);
  // 以对象调用的形式调用fun,此时this指向context,也就是传入的需要绑定的this指向
  let res = arguments.length > 1 ? context.fun(...args ) : context.fun();
  //不删除该方法会对传入对象造成污染
  delete context.fun;

  return res;
}
/************************************************************************/
//使用:
let developer = {
  parent: function (a,b){
    console.log(a,b)
   console.log(this.name)
  }
}
let obj={
 name:'张三'
}
developer.parent.myCall(obj,1,2)  // 1 2 张三
apply的简易模拟实现(es6)
  • 思路
    apply实现的思路与call基本相同,我们只需要对参数进行不同处理即可
    例如:Parent.apply(this,[1,2,3]);
Function.prototype.myApply = function (context = window) {
  // context为调用的上下文,this此处为函数,将这个函数作为context的方法
  context.fun = this;
  // 以对象调用的形式调用fun,此时this指向context,也就是传入的需要绑定的this指向
  let res= arguments[1] ? context.fun(...arguments[1]) : context.fun();
  //不删除该方法会对传入对象造成污染 
  delete context.fun;
  return res;
}
/************************************************************************/
//使用:
let developer = {
  parent: function (a,b){
    console.log(a,b)
   console.log(this.name)
  }
}
let obj={
 name:'张三'
}
developer.parent.myApply (obj,[1,2])  // 1 2 张三
bind的简易模拟实现(es6)
  • 思路
  1. 函数定义在哪里 ?
    bind是可以被所有方法调用的,所以毫无疑问的定义在 Function的原型上!
  2. 函数接收参数 ?
    bind函数返回一个绑定函数,最终调用需要传入函数实参和绑定函数的实参!!
    例如:Parent.bind(this)(1,2,3);
  3. 如何显式绑定this ?
    如果调用者是函数,被某一个对象所拥有,那么该函数在调用时,内部的this指向该对象。
Function.prototype.myBind = function(context) {
  //对context进行深拷贝,防止污染
  context = JSON.parse(JSON.stringify(context)) || window;
  // context为调用的上下文,this此处为函数,将这个函数作为context的方法
  context.fun = this;
  //获取实参
  let args = Array.from(arguments).slice(1);

  //bind返回一个绑定的函数,等待调用
  return function () {
     //这里需要注意一点的是需要对bind函数的实参和返回的绑定函数的实参进行参数合并,调用时传入;
    let allArgs= args.concat(Array.from(arguments));
    // 以对象调用的形式调用fun,此时this指向context,也就是传入的需要绑定的this指向
    return allArgs.length > 0 ? context.fun(...allArgs) : context.fun();
  }
}
/************************************************************************/
//使用:
let developer = {
  parent: function (a,b){
    console.log(a,b)
   console.log(this.name)
  }
}
let obj={
 name:'张三'
}
developer.parent.myBind(obj)(1,2)  // 1 2 张三

原文参考: 面试官:你能手写实现call,apply,bind方法吗?

相关文章

网友评论

      本文标题:手写bind,apply,call方法

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