javascript

js中 Call Apply 解析

2020-10-20  本文已影响0人  Viker_bar

需要提前知道的知识


一:基本语法

 /*
  *
  *@Des Call语法
  *@Param thisArg: 可选的 在function 函数运行时使用的 this 值
  *@Param arg1, arg2, ... 可选的 指定的参数列表
  *
  **/
  function.call(thisArg, arg1, arg2, ...)


/*
  *
  *@Des Apply语法
  *@Param thisArg: 可选的 在function函数运行时使用的this值
  *@Param [argsArray] 可选的 一个数组或者类数组对象
  *
  **/
 function.apply(thisArg, [argsArray])



二:Apply、Call 方法都会使函数立即执行,因此它们也可以用来调用函数 

function func() {
    console.log('Hello');
}
func.call(); // Hello

先看一段代码?

    function Aee(){
        this.userName = "Aee";
        this.userAge = "18";
        this.userPhone = "15699999999";
        this.getUserName = function(){
            return this.userName;
        }
        this.getUserAge = function(){
            return this.userAge;
        }
    }

    function Bee(){
        Aee.call(this);
        this.userAge = "Bee19";
    }

    function Cee(){
        Bee.call(this);
        this.userName = "Cee";
    }
    var cec = new Cee();
    console.log(cec.userName);    //Cee
    console.log(cec.userAge);     //Bee19
    console.log(cec.userPhone);   //15699999999

我们来翻译一下上面的代码:

    function Aee(){
        this.userName = "Aee";
        this.userAge = "18";
        this.userPhone = "15699999999";
        this.getUserName = function(){
            return this.userName;
        }
        this.getUserAge = function(){
            return this.userAge;
        }
        this.getUserPhone = function(){
            return this.userPhone;
        }
    }

    function Bee(){

        Aee.call(this); //这句话相当于新增一个指向Aee构造函数的指针(注意:不是改变指针指向,是新增一个新的指针)

        //新增指针指向的内容如下:(我继承于Aee构造函数中的内容)
        this.userName = "Aee";
        this.userAge = "18";
        this.userPhone = "15699999999";
        this.getUserName = function(){
            return this.userName;
        }
        this.getUserAge = function(){
            return this.userAge;
        }
        this.getUserPhone = function(){
            return this.userPhone;
        }

        //我本来就有,不是继承的
        this.userAge = "Bee19";
    }

    function Cee(){

        Bee.call(this); //这句话相当于新增一个指向Bee构造函数的指针(注意:不是改变指针指向,是新增一个新的指针)

        //新增指针指向的内容如下:(我继承于Aee构造函数中的内容)
        this.userName = "Aee";
        this.userAge = "18";
        this.userPhone = "15699999999";
        this.getUserName = function(){
            return this.userName;
        }
        this.getUserAge = function(){
            return this.userAge;
        }
        this.getUserPhone = function(){
            return this.userPhone;
        }
        //新增指针指向的内容如下:(我继承于Bee构造函数中的内容)
        this.userAge = "Bee19";

        //我本来就有,不是继承的
        this.userName = "Cee";
    }

最终结果翻译结果如下:

   function Aee(){
        this.userName = "Aee";
        this.userAge = "18";
        this.userPhone = "15699999999";
        this.getUserName = function(){
            return this.userName;
        }
        this.getUserAge = function(){
            return this.userAge;
        }
        this.getUserPhone = function(){
            return this.userPhone;
        }
    }

    function Bee(){

        this.userName = "Aee";
        this.userAge = "18";
        this.userPhone = "15699999999";
        this.getUserName = function(){
            return this.userName;
        }
        this.getUserAge = function(){
            return this.userAge;
        }
        this.getUserPhone = function(){
            return this.userPhone;
        }
        this.userAge = "Bee19"; 
    }

    function Cee(){

        this.userName = "Aee";
        this.userAge = "18";
        this.userPhone = "15699999999";
        this.getUserName = function(){
            return this.userName;
        }
        this.getUserAge = function(){
            return this.userAge;
        }
        this.getUserPhone = function(){
            return this.userPhone;
        }
        this.userAge = "Bee19";
        this.userName = "Cee";
    }

    var cec = new Cee();
    console.log(cec.userName);    //Cee
    console.log(cec.userAge);     //Bee19
    console.log(cec.userPhone);   //15699999999

用白话再翻译一遍


Aee.call(this);
1:立即运行Aee函数
2:建立新的指针指向Aee构造函数(实现继承的关键)
3:开始获取相关属性或调用相关函数,如果当前作用域里面没有找到,则去查找call函数第一个参数对象,当前也就是this,如果还没有找到,则去Aee里去查找

Bee.call(obj);
1:立即运行Bee函数
2:建立新的指针指向Bee构造函数(实现继承的关键)
3:开始获取相关属性或调用相关函数,如果当前作用域里面没有找到,则去查找call函数第一个参数对象,当前也就是obj,如果还没有找到,则去Bee里去查找

var num = [1,3,5,7,2,-10,11];
Math.max.apply(Math, num);

1:立即运行Math.max函数
2:建立新的指针指向Math.max构造函数(实现继承的关键)
3:开始获取相关属性或调用相关函数,如果当前作用域里面没有找到,则去Math里面去查找max函数,如果还没有找到,则去Math.max里去查找(实际不会走到这一步,上一步已经结束查找了)


var fakeArr = {0:'a',1:'b',length:2};
Array.prototype.slice.call(fakeArr);

1:立即运行Array.prototype.slice函数
2:建立新的指针指向Array.prototype.slice构造函数(实现继承的关键)
3:开始获取相关属性或调用相关函数,如果当前作用域里面没有找到,则去fakeArr里面去查找Array.prototype.slice函数,如果还没有找到,则去Array.prototype.slice里去查找,实际它查找的是Array对象下是否有slice函数

总结:

1:call和apply的使用本质是作用域链的动态添加,且遵循作用域链的查找规则,不管call和apply嵌套层级多深(先查找自身,然后根据嵌套逻辑逐级往上查找)
2:javascript 继承的本质不是复制,是新增指针指向

上一篇下一篇

猜你喜欢

热点阅读