SOURCE

// bind、call、apply 都是用来改变函数运行时的 this 指向问题

var name = 'window'

function test() {
    console.log(...arguments)
    console.log(this.name)
    return 'test function'
}

// console.log(test(1, 2, 3))
// console.log(test.bind({ name: 'bind'}, 1, 2, 3)(4, 5))
// console.log(test.call({ name: 'call'}, 1, 2, 3))
// console.log(test.apply({ name: 'apply'}, [1, 2, 3]))

// 使用 bind 在修改源函数的情况下,重复绑定无效
// 只会生效第一次的绑定
// test = test.bind({ name: 'bind'}, 1, 2, 3)
// test = test.bind({ name: 'bind1'}, 4, 5, 6)
// console.log(test(7, 8))

Function.prototype.lBind = function (target) {
    // 截取传进来的除目标对象之外的其余参数
    var _argu = Array.prototype.slice.call(arguments, 1)
    var _this = this

    return function () {
        // 接收新的参数
        _argu = _argu.concat(Array.prototype.slice.call(arguments))

        Object.defineProperty(target, '_fn', {
            enumerable: false,  // 不可枚举
            writable: false,    // 不可写
            configurable: true, // 可以配置 才可以删除
            value: _this
        })
        var result = target._fn(..._argu)

        delete target._fn

        return result
    }
}

// console.log(test.lBind({ name: 'lBind' }, 1, 2, 3)(4, 5))
// test = test.lBind({ name: 'lBind' }, 1, 2, 3)
// test = test.lBind({ name: 'lBind' }, 4, 5, 6)
// console.log(test(7, 8))

Function.prototype.lCall = function (target) {
    // 截取传进来的除目标对象之外的其余参数
    var _argu = []
    for (var i in arguments) {
        if (i !== '0') _argu.push(arguments[i])
    }
    var _this = this

    Object.defineProperty(target, '_fn', {
        enumerable: false,  // 不可枚举
        writable: false,    // 不可写
        configurable: true, // 可以配置 才可以删除
        value: _this
    })
    var result = target._fn(..._argu)

    delete target._fn

    return result
}

// console.log(test.lCall({ name: 'lCall'}, 1, 2, 3))

Function.prototype.lApply = function (target) {
    // 截取传进来的除目标对象之外的其余参数
    var _argu = arguments[1] || []
    var _this = this

    Object.defineProperty(target, '_fn', {
        enumerable: false,  // 不可枚举
        writable: false,    // 不可写
        configurable: true, // 可以配置 才可以删除
        value: _this
    })
    var result = target._fn(..._argu)

    delete target._fn

    return result
}

console.log(test.lApply({ name: 'lApply'}, [1, 2, 3]))
console 命令行工具 X clear

                    
>
console