编辑代码

// function(this,['hello'])

// this,[name,password...]
Function.prototype.newApply = function (context) {
    context = context || window

    context.fn = this

    let result = arguments[1] ? context.fn(...arguments[1]) : context.fn();

    delete context.fn

    return result
}



// function.bind(this),会生成一个新方法


Function.prototype.newBind = function () {
    // 改变this的指向
    const _this = this;
    //接受参数args,第一项参数是this,第二项到最后一项是函数传参
    const args = Array.prototype.slice.call(arguments); // 将伪数组转换成真的数组
    const newThis = args.shift();

    // 返回一个新方法
    return function () {
        return _this.newApply(newThis, args)
    }
}

// this,name,password...
Function.prototype.newCall = function (context, ...args) {
    context = context || window

    context.fn = this

    let result = context.fn(...args)

    delete context.fn

    return result
}

function a(name, password) {
    console.log(name, password, this)
    return name + password
}

function b() {
    console.log("不带参数", this)
    return "不带参数的"
}

// 要执行
const aa = a.newCall(b, '徐秋实', '123456')
console.log(aa)
const bb = b.newCall(a)
console.log(bb)


// 原生call
// 接收的参数是this,a,b,c,d,e...等参数
Function.prototype.originCall=function(context){
    // 传进来的this值,如果存在就传进来的this,如果不存在,就指向window
    context = context || window

    // 在context上定义一个函数,这里的this就是originCall本体的this,但是这里是传进来的context上定义的函数,所以fn的this指向是context
    context.fn=this

    // 传入的所有参数包括context都在arguments里面,需要取出来
    const args=Array.prototype.slice.call(arguments); // 将伪数组转换成真的数组
    // 删除context参数,取剩余所有参数
    args.shift()
    console.log(args)

    // 将定义的函数执行
    const result = context.fn(...args)

    // 删除原始context上定义的函数,将context保持原样
    delete context.fn

    return result
}



// 手写新bind函数
Function.prototype.newBindTwo=function(){
    const _this=this;
    const args=[...arguments];
    const newThis=arges.shift();

    // 返回一个新的函数
    return function () {
        return _this.newApplyTwo(newThis,args)
    }
}

// 手写apply函数,apply传参(this,[xxx,xxx,xxx])
Function.prototype.newApplyTwo = function (context) {
    context = context || window ;
    console.log(context,"---------------context"); // 新的传入的this对象
    context.fn = this;

    // 返回值是执行完函数的返回值
    const result = arguments[1]? context.fn(arguments[1]) : context.fn();

    delete context.fn

    return result
}


function testApply(name){
    return name
}

function testApply2(name){
    return name+"/--2"
}

const name = testApply.newApplyTwo(testApply2,'徐秋实')


// 手写call函数不使用apply
Function.prototype.newCallTwo = function (context) {
    context = context || window ;
    context.fn = this;

    const args=[...arguments];
    args.shift();
    const result =context.fn();

    delete context.fn;

    return result;
}