bind apply call 的代码实现

142 阅读2分钟

区别

  • 三者都可以改变函数的this指向。
  • 三者第一个参数都是this要指向的对象,如果没有这个参数或者参数为undefined或者null,则默认指向全局window
  • 三者都可以传参,但是apply传入的是数组,call传入的是参数列表。
  • applycall一次传入所有参数,bind可以一次传入部分参数,下次调用返回的函数时再传入其他参数。
  • bind是返回绑定this后的函数,用于后续调用。apply``call是立即执行绑定this后的函数。

实现

bind

Function.prototype.customBind = function (context, ...bindArgs) {

    // context 是传入 的 this
    // binsArgs 是传入的参数

    const self = this // 当前函数本身
    return function (...args) {

        // 拼接参数
        const newArgs = bindArgs.concat(args)

        return self.apply(context, newArgs)

    }
}

function fn(a, b, c) {

    console.log(this, a, b, c);
}

fn.customBind({ x: 100 }, 20, 30)

apply

Function.prototype.customApply = function (context, argsArray) {

    // 若传入的this指向为空,则将其指向 window
    if (context == null) context = globalThis
    // 将普通类型的值包装为对象类型
    if (typeof context !== 'object') context = new Object(context)

    // 创建一个唯一的 key ,将当前函数绑定到 context 对象上去
    const fnKey = Symbol()
    context[fnKey] = this // this 就是当前函数

    // 通过 obj.fn() 的方式执行当前函数,当前函数的 this指向自然便指向了 context
    const res = context[fnKey](...argsArray)

    // 执行完函数后删除 context 上的这个函数
    delete context[fnKey]

    // 返回结果
    return res
}

call

Function.prototype.customCall = function (context, ...callArgs) {

    // 若传入的this指向为空,则将其指向 window
    if (context == null) context = globalThis
    // 将普通类型的值包装为对象类型
    if (typeof context !== 'object') context = new Object(context)

    // 创建一个唯一的 key ,将当前函数绑定到 context 对象上去
    const fnKey = Symbol()
    context[fnKey] = this // this 就是当前函数

    // 通过 obj.fn() 的方式执行当前函数,当前函数的 this指向自然便指向了 context
    const res = context[fnKey](...callArgs)

    // 执行完函数后删除 context 上的这个函数
    delete context[fnKey]

    // 返回结果
    return res
}

function test(a, b, c) {
    console.log(this, a, b, c);
}

test.customCall({ x: 100 }, 20, 30)