call方法深入

作者: 阿九是只大胖喵 | 来源:发表于2017-03-04 13:33 被阅读256次

    首先看数组中的一个方法:
    Array.prototype.slice = function() {}

       var ary = [12, 23, 34];
        // ary.slice -> ary这个实例,通过原型链的查找机制,找到Array.prototype上的slice方法,此时是该函数的地址
        // ary.slice(); -> 让找到的slice方法执行,在执行slice方法的过程中,才把ary数组进行截取
    

    call方法的作用:
    -> 首先让原型上的call方法执行,在执行call方法的时候,让fn方法中的this变为第一个参数值obj;然后再把fn这个函数执行。

        var obj = {
            name: 'derrick'
        }
        function fn() {
            console.log(this);
        }
        fn(); // this -> window
        fn.call(obj); // this -> obj
    

    自己模拟内置的call方法,写一个myCall方法,深入探讨call方法执行的原理。

        Function.prototype.myCall = function (context) {
            // -> myCall方法中的this就是当前要操作和改变其this关键字的那个函数
    
            // -> 1. 让fn中的this关键字变为context的值 -> obj
            // -> 让this这个函数中的"this关键字"变为context
            // var that = eval(this.toString().replace('this', context));
    
            // -> 2. 让fn方法在执行
            this();
        }
        fn.myCall(obj); // -> myCall方法中的this是fn
    
        function sum() {
    
        }
        sum.myCall(obj); // -> myCall方法中this是sum
    

    下面看一道面试题:

        function fn1() {
            console.log(1);
        }
        function fn2() {
            console.log(2);
        }
    
        fn1.call(fn2); // -> 首先fn1通过原型链机制找到Function.prototype上的call方法,并且让call方法执行,
        // -> 此时call这个方法中的this就是要操作fn1 -> 在call方法代码的执行过程中,首先fn1中的"this关键字"变为fn2,
        // 再让fn1这个方法执行 -> 最终执行结果为 1
    
        fn1.call.call(fn2); // -> fn1.call 首先fn1通过原型链机制找到Function.prototype上的call方法,
        // 然后再让call方法通过原型再找到Function原型上的call(因为call本身的值也是一个函数,所以同样可以找到Function.prototype),在
        // 第二次再找到call的时候,让方法执行,方法中的this是fn1.call, 首先让这个方法中的this变为fn2,然后再让fn1.call执行
        // -> 输出结果为 2
    

    再次分析:

        function xxx(context) {
            // 1. 让this这个函数中的"this关键字"变为context
            // 2. 让this方法执行
            this();
        }
        Function.prototype.myCall = xxx;
        fn1.call.call(fn2);
        // -> fn1.call -> xxx;
        // -> xxx.call(fn2) -> 先让call方法执行,call中this是xxx,让xxx中的this变为fn2,
        // 再让xxx执行 -> 2
    
        fn1.call.call.call.call.call(fn2); // 2
    
        Function.prototype.call(fn1); // Funciton.prototype是空函数,将其执行就是空函数执行,直接销毁
        Function.prototype.call.call.call.call(fn1); // fn1() -> 1
    

    相关文章

      网友评论

        本文标题:call方法深入

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