JS apply 和 call 的实现

时间:2023-01-31 18:35:50

很早之前的一篇博客写了bind的实现,是基于apply的,感兴趣的朋友看完这篇文章可以接着看看bind的实现。

apply 和 call 主要就是传参的区别。这里就不多说了,直接看代码。

    //call 实现
    Function.prototype.myCall = function(context) {
        
        context.fn = this
        
        var args = [...arguments].slice(1)
        
        var result = context.fn(...args)
        
        delete context.fn
        
        return result
    }

实例

   var obj = {
        name: 'hx'
    }

    function foo(sex, age) {
        console.log(sex + ' ' + this.name + ' ' + age);
    }

    foo.myCall(obj, 'boy', '25');// boy hx 25  

 实现原理:其实就是把fn放在obj下面执行(后面得把obj.fn从obj上删除了,保持obj的孑然之身嘛!),context.fn = this,obj这个对象就不止name属性了吧,多了fn属性,就是函数 foo。然后context.fn()执行的时候,由于fn是context也就   是obj调用的,那么在foo内部执行的时候, this.name就会找到obj的name,变相达成了实现this指向的更改或者说是其他对象的劫持。

   如果上面关于context.fn还不明白的话,那看下面这个

   var a = {
        b:'11',
        c:function () {
            console.log(this,this.b)
        }
    }
    a.c() // 11  

 接着,apply跟call就是在参数arguments上的处理有一点区别而已

    Function.prototype.myApply = function(context) {

        var context = context || window

        context.fn = this

        var result;

        // 需要判断是否存储第二个参数,如果存在,就将第二个参数展开

        if(arguments[1]) {
            result = context.fn(...arguments[1])
        } else{
            result = context.fn()
        }

        delete context.fn

        return result
    }

 传送门:bind的实现