美文网首页
call和apply自定义实现

call和apply自定义实现

作者: 零界梦忆 | 来源:发表于2020-01-18 16:54 被阅读0次

本文需要读者熟悉call和apply的基本使用以及this的指向相关知识
首先来看一段代码

    <script>
        var value = 'window'
        var obj = {
            value:'obj'
        }
        function show(){
            console.log(this.value)
        }
        show()
        show.call(obj)
        show.call(null)
    </script>
输出结果

接着思考下面的代码

    <script>
        var value = 'window'
        var obj = {
            value:'obj'
        }
        function show(){
            console.log(this.value)
        }
        obj.show = show
        obj.show()
        delete obj.show
    </script>

这段js代码中后面三行(script标签以上)模拟了show.call(obj)的功能,先在obj上定义一个属性,属性值是show函数,熟悉this指向的同学就会明白此时执行obj.show()的话show方法是obj对象上的一个方法,那么此时show方法内部的this指向的就是obj。最后将obj中的show属性用delete移除。

以此为基础

    <script>
        var value = 'window'
        var obj = {
            value:'obj'
        }
        function show(){
            console.log(this.value)
        }
        Function.prototype.newCall = function(ctx) {
            // 这个this指向的就是函数实例对象中的this(此时是show函数,我们通过this可以拿到show函数实例对象)
            // 将函数实例对象添加到某个对象上(此时等同于obj.fn = show)
            ctx.fn = this
            // 执行这个对象上的那个函数(相当与obj.show())
            // 此时这个函数里面的this指向的就是这个要改变的对象(show函数实例里面的this指向的是obj对象)
            ctx.fn()
            // 删除对象的方法属性(删除在前面添加都obj里面的fn方法)
            delete ctx.fn
        }
        show.newCall(obj)
    </script>

上述的方法可以实现call中改变this的功能,但是用过call的读者应该发现,call方法不只能接受一个参数。
接着实现完整的call方法
具体实现需要具备arguments和展开运算符相关知识

    <script>
        var value = 'window'
        var obj = {
            value:'obj'
        }
        function show(name,age){
            console.log(this.value)
            return {
                name,
                age
            }
        }

        /*****call方法*****/
        var result = show.call(obj,'fu',21)
        console.log(result)


        /*****自定义方法*****/
        Function.prototype.newCall = function() {
            // 获取arguments中的第一个元素,也就是传入的第一个实参,如果为null的话默认是window
            var ctx = arguments[0] || window
            // 这个this指向的就是函数实例对象中的this(此时是show函数,我们通过this可以拿到show函数实例对象)
            // 将函数实例对象添加到某个对象上(此时等同于obj.fn = show)
            ctx.fn = this
            // 创建一个数组,将arguments中的值放入数组中
            var arr = new Array(...arguments)
            // 将数组中第一个元素去掉
            arr.splice(0,1)
            // 执行这个对象上的那个函数(相当与obj.show('fu',21))
            // 此时这个函数里面的this指向的就是这个要改变的对象(show函数实例里面的this指向的是obj对象)
            // 此时不能直接return, 否则后续代码不能继续执行
            var result =  ctx.fn(...arr)
            // 删除对象的方法属性(删除在前面添加都obj里面的fn方法)
            delete ctx.fn
            // 返回方法执行的结果
            return result
        }

        var result2 = show.newCall(obj,'fu',21)
        console.log(result2)
    </script>

最后实现apply
知道了怎么实现call,实现apply就非常容易了

        Function.prototype.newApply = function(ctx,argsArr){
            ctx.fn = this || window
            if(!argsArr) {
                var result = ctx.fn()
            } else {
                var result = ctx.fn(...argsArr)
            }
            delete ctx.fn
            return result
        }

总结:要学会自定义call和apply,最关键的还是熟悉js中this的指向问题

相关文章

网友评论

      本文标题:call和apply自定义实现

      本文链接:https://www.haomeiwen.com/subject/wywkzctx.html