彻底理解并手写call和apply方法

165 阅读2分钟

apply接受两个参数,第一个参数是this的指向,第二个参数是数组,当第一个参数为null、undefined的时候,默认指向window(因为apply第二个参数必须为数组,不是数组会报错,一些文章在写这个方法的时候没有进行判断)

    测试数据
            var person = function (city, country) {
        return '姓 ' + this.firstName + " 名 " + this.lastName + " 出生在 " + city + country
    }
    var student = {
        firstName: "张",
        lastName: "三"
    }
    Function.prototype.newApply = function (student) {
        // 第一个参数为 null 和 undefined 时 
        // this 值会自动指向全局对象(浏览器中为window)
        if (student === null || student === undefined) return student = window
        //定义一个唯一的值
        const sole = Symbol()
        //在student对象上临时添加一个属性sole
        //因为是person函数调用 所以this指向person
        //此时student.sole = person函数
        student.sole = this
        let result
        //先判断第二个参数是否为空 
        if ((arguments[1]) == undefined) result = student.sole()
        //因为apply的第二个参数为数组 所以判断第二个参数是否为数组
        if (!(arguments[1] instanceof Array)) return new Error('fail')
        //判断是否有第二个参数
        result = student.sole(...arguments[1])
        //删除临时定义的方法
        delete student.sole
        //返回结果
        return result
    }
    const res = person.newApply(student, ["中国", "北京"]);
    console.log(res) //姓 张 名 三 出生在 中国北京

call方法的第一个参数也是this的指向,后面传入的是一个参数列表,当第一个参数为null或undefined的时候,表示指向window

    var person = function (city, country) {
        return '姓 ' + this.firstName + " 名 " + this.lastName + " 出生在 " + city + country
    }
    var student = {
        firstName: "张",
        lastName: "三"
    }
    Function.prototype.newCall = function (student) {
        // 第一个参数为 null 和 undefined 时 
        // this 值会自动指向全局对象(浏览器中为window)
        if (student === null || student === undefined) return student = window
        //定义一个唯一的值
        const sole = Symbol()
        //在student对象上临时添加一个属性sole
        //因为是person函数调用 所以this指向person
        //此时student.sole = person函数
        student.sole = this
        //获取参数  删除第一个参数 
        //此时arg为["中国", "北京"]
        const arg = [...arguments].slice(1)
        //将arg作为参数 调用student.sole函数 也就是person函数
        const result = student.sole(...arg)
        //为了不改变原对象 删除student.sole 
        delete student.sole
        //返回 person函数返回的值
        return result
    }
    const res = person.newCall(student, "中国", "北京");
    console.log(res) //姓 张 名 三 出生在 中国北京