手写 call, apply,bind

195 阅读1分钟

call

const person = {
            name: 'zaaa',
            test: function(age, sex) {
                console.log(this.name + '已经' + age + ',' + '是个' + sex ')
            }
        }

        var son = {

        }
        Function.prototype.newCall = function() {
                if (typeof this !== 'function') return new Error('The ' + this + ' should be a function')
                    // 得到当前的方法
                let funcThis = this
                    // 其余参数
                let arr = [...arguments]
                    // 要改变到的对象 --- 如果没有传参,就指向window
                let to = arr.shift() || window
                arr = arr[0]
                    // 得到的方法加在要改变到的对象身上
                to.fn = funcThis
                    // 执行
                let result = to.fn(...arr)

                delete to.fn
                return result
            }
            
            //person.test.newCall(son, 12, 'man')

输出结果:undefined已经12,是个man

此时this已经改变了,this.name当然是undefinded了!

apply

apply 实现方法类似,只要把第二个参数改成数组就行

       Function.prototype.newApply = function() {
               if (typeof this !== 'function') return new Error('The ' + this + ' should be a function')

               // 得到当前的方法
               let funcThis = this
               let arr = [...arguments]
                   // 要改变到的对象 --- 如果没有传参,就指向window
               let to = arr.shift() || window
                   // 得到的方法加在要改变到的对象身上
               arr = arr[0]
               to.fn = funcThis
                   // 执行
               let result = arr ? to.fn(...arr) : to.fn()

               delete to.fn
               return result
           }
           // person.test.newApply(son, [12, 'man'])

bind

bind 方法与 call 类似, 只是它变成了一个回调函数

        Function.prototype.newBind = function() {
            if (typeof this !== 'function') return new Error('The ' + this + ' should be a function')
                // 得到当前的方法
            let funcThis = this
                // 其余参数
            let arr = [...arguments]
                // 第一个参数
            let to = arr.shift() || window
                // 第二个参数
            arr = arr[0]

            return function() {
                funcThis.newCall(to, arr)
            }
        }
        let a = person.test.newBind(son, [12, 'man'])
        a()