call、apply、bind实现原理

语法

method.call(obj , argument1 , argument2...)
method.apply(obj , [argument1,argument2..])
method.bind(obj , argument1 , argument2...)

区别

相同点
  1. 三者都可以改变函数内部this的指向
  2. 三者第一个参数都是this要指向的对象,如果参数为空、undefined、null,默认指向window
不同点
方法 参数 是否立即执行
call 第二个参数之后,传递的是参数列表
apply 第二个参数是数组
bind 第二个参数之后,可分多次传入 ×

作用

  1. 改变参数传入方式
let arr = [1,2,3,4]
Math.max.apply(null, arr);  // 4
  1. 扩充作用域, 实现对象和属性之间的解耦
var color = 'red';
var obj = { color : 'blue'};
function showColor(){
    alert(this.color);
}

showColor();  //red
showColor.call(window);  //red
showColor.call(obj);  //blue

源码实现

call
Function.prototype.call = function (context, ...args) {
    // 绑定对象为null时,默认指向window对象
    context = context || window
    context.fn = this
    let res = context.fn(...args)
    // 调用结束后,删除对象上添加的方法
    delete context.fn
    // 返回执行方法的结果
    return res
}
apply
Function.prototype.apply = function (context, arg) {
    // 绑定对象为null时,默认指向window对象
    context = context || window
    context.fn = this
    let res = arg ? context.fn(...arg) : context.fn()
    // 调用结束后,删除对象上添加的方法
    delete context.fn
    // 返回执行方法的结果
    return res
}
bind
Function.prototype.bind = function (context, ...arg1) {
    let _this = this
    return function (...arg2) {
        // 组合参数
        let arg = arg1.concat(arg2)

        // 绑定对象为null时,默认指向window对象
        context = context || window
        context.fn = _this
        let res = context.fn(...arg)
        // 调用结束后,删除对象上添加的方法
        delete context.fn
        // 返回执行方法的结果
        return res
    }
}
posted @ 2022-04-15 16:22  孟冰er  阅读(80)  评论(0编辑  收藏  举报