简述JS八股文——bind call apply

259 阅读1分钟

概念

**apply call 和bind** 允许为不同的对象分配和调用属于一个对象的函数/方法。同时它们可以改变函数内 this 的指向。

区别

  1. apply 和 call 接收的参数形式不同;
  2. apply 和 call 都是直接调用函数并得到函数执行结果,而 bind 会返回待执行函数,需要再次调用。

使用

    
   const parent = { 
       name: 'parent', 
       sayPerson (age, addr) {
           return { name: this.name, age, addr } 
           } 
       }
    
    const person = parent.sayPerson(60, 'shenzhen'); 
    // {name: "parent", age: 60, addr: "shenzhen"}

    const son = { name: 'son' }
    const callPerson = parent.sayPerson.call(son, 26, 'shenzhen'); 
    // {name: "son", age: 26, addr: "shenzhen"}  (可接收多个参数)
    
    const applyPerson = parent.sayPerson.apply(son, [26, 'shenzhen']);
    // {name: "son", age: 26, addr: "shenzhen"} (接收数组)
    
    const sayPersonFn = parent.sayPerson.bind(son, 26, 'shenzhen'); 
    const bindPerson = sayPersonFn(); 
    // {name: "son", age: 26, addr: "shenzhen"} (return 一个函数)
    

简单实现

  • call&apply:

    Function.prototype.myCall = function(context=window){
        context.fn = this  //函数的调用者 => 被借用的函数   this:被借用的函数 
        const args = [...arguments].slice(1) //传递的参数
        const result = context.fn(...args) //执行借用到的函数
        delete context.fn //第一步为myCall添加了被借用对象的方法,用完应当删除
        return result //return 执行结果
    }
    
    Function.prototype.myApply = function(context){
        context.fn = this
        const args = [...arguments][1] //区别
        const result = context.fn(...args)
        delete context.fn
        return result
    }

  • bind:

Function.prototype.myBind = function (...args) { 
    // 实际就是多包了层待执行函数 
    return () => { 
        return this.applyFn(args[0], (args || []).slice(1)); 
    }
}