编辑代码

//实现call
Function.prototype.myCall = function () {
   const [context, ...argu] = [...arguments]
   context.fun = this // 这块的this,就是我们调用call的方法
   context.fun(...argu)
   delete context.fun
}
const obj = {
    a: '我是对象中的'
}

function fn() {
    console.log(this.a, ...arguments)
}

// function myCallFn(fn, context, ...argu) {
//     context.fun = fn
//     context.fun(...argu)
//     delete context.fun
// }
// myCallFn(fn, obj, [1,2], '23231321' ,'333')
fn.myCall(obj, [1,2], 200 ,'333', 1)

// 实现一个apply
Function.prototype.myApply = function() {
    const [context, argu] = [...arguments]
    context.fun = this // 改变this指向
    let res = argu.length > 0 ? context.fun(...argu) : context.fun()
    delete context.fun
    return res
}

function fnApply() {
    console.log(this.a); // 1
     console.log([...arguments]); // 1
    return [...arguments]
}

let s = fnApply.myApply(obj, [1,2,3,4,5])
console.log(s)

// 实现一个bind
// bind返回一个可执行的函数
// 1. 使用闭包模拟bind
Function.prototype.myBind = function() {
    const [context, ...args] = [...arguments];
    return () => {
        return this.apply(context, [...args])
    }
}

const obj2 = {
    value: 1,
    fn: function(name) {
        console.log('bind调用 '+this.value, name)
    }
}
let a = obj2.fn
a() // 因为是window调用,所以会去window上找
a.bind(obj2,'周斌')() // 传参数
a.myBind(obj2, '周斌')()