SOURCE

// 定义变量
const obj = {
    a: 1,
    fn: function (num = 1, m = 1) {

        console.log(this.a * num * m)
    }
}
const obj2 = { a: 22 }
this.a = 3
// 测试
const t = obj.fn
t()  //window.a  3 this 指向window
obj.fn()  // obj.a 1 this 指向最后调用它的对象obj
// 改变this 指向 obj2 obj2.a
obj.fn.apply(obj2, [2]) // 2*2=4
obj.fn.call(obj2, 4)    // 2*4=8
obj.fn.bind(obj2)(5)    // 2*5 =10
obj.fn.bind(obj2, 5)()    // 2*5 =10

// 改写call方法
Function.prototype.myCall = function (context) {
    if (typeof this !== 'function') {
        throw new Error('Not Function')
    }
    context = context || window // 初始化this指向,未传入绑定this,默认为window
    context.fn = this // 拷贝被执行的函数
    // 判断是否传入参数,通过arguments 取出被执行函数的参数
    arguments[1] ? context.fn(...[].slice.call(arguments, 1)) : context.fn()
    // 删除方法
    delete context.fn
}
// 测试
obj.fn.myCall() // this.a 3
// 改写apply方法
Function.prototype.myApply = function (context) {
    if (typeof this !== 'function') {
        throw new Error('Not Function')
    }
    context = context || window // 初始化this指向,未传入绑定this,默认为window
    context.fn = this // 拷贝被执行的函数
    // 判断是否传入参数,通过arguments 取出被执行函数的参数
    arguments[1] ? context.fn(...arguments[1]) : context.fn()
    // 删除方法
    delete context.fn
}
// 测试
obj.fn.myApply() // this.a 3
// 改写bind方法
Function.prototype.myBind = function (context) {
    if (typeof this !== 'function') {
        throw new Error('Not Function')
    }
    context = context || window // 初始化this指向,未传入绑定this,默认为window
    // 判断是否传入参数,通过arguments 取出被执行函数的参数
    let args = arguments[1] ? [].slice.call(arguments, 1) : []

    return (...params) => {
        this.apply(context, [...args, ...params])
    }
}
// 测试
obj.fn.myBind(obj2, 3)(9) // 2*3*9= 54
console 命令行工具 X clear

                    
>
console