bind、call、apply的区别(手写系列)

255 阅读1分钟

简要回答

  • 改变函数执行时的this指向
  • call/apply:fun执行的结果
  • bind:返回fun的拷贝,并拥有指定的this值和初始参数
  • apply第二个参数为数组,数组内的值为传给fun的参数
  • 调用call/apply/bind的必须是个函数

语法

fun.call(thisArg, param1, param2, ...)
fun.apply(thisArg, [param1,param2,...])
fun.bind(thisArg, param1, param2, ...)

var obj1={
    name:"小明",
    fn1:function(val1,val2) {
        console.log(this.name,val1,val2);
    }
}       
var obj2={
    name:"小红",
    fn2:function() {
        console.log(this.name);
    }
} 
console.log(this.obj1.fn1.call(obj2,111,222))
console.log(this.obj1.fn1.apply(obj2,[111,222]))  
console.log(this.obj1.fn1.bind(obj2,111,222)())  

//输出
//小红 111 222
//小红 111 222
//小红 111 222

手写一个call

  1. 根据call的规则设置上下文对象,也就是this的指向。
  2. 通过设置context的属性,将函数的this指向隐式绑定到context上
  3. 通过隐式绑定执行函数并传递参数。
  4. 删除临时属性,返回函数执行结果

Function.prototype.myCall = function (context, ...arr) {
    if (context === null || context === undefined) {
        context = window  
        // 指定为 null 和 undefined 的 this 值会自动指向全局对象(浏览器中为window)
    } else {
        context = Object(context)   
        // 值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的实例对象    
    }
    const specialPrototype = Symbol('特殊属性Symbol') // 用于临时储存函数
    context[specialPrototype] = this  // 函数的this指向隐式绑定到context上
    let result = contextspecialPrototype  // 通过隐式绑定执行函数并传递参数
    delete context[specialPrototype]  // 删除上下文对象的属性
    return result  // 返回函数执行结果
}