• apply call this arguments caller callee


    JavaScript为函数对象定义了两个方法:apply和call,它们的作用都是将函数绑定到另
    外一个对象上去运行,两者仅在定义参数的方式有所区别:

    Function.prototype.apply(thisArg,argArray);
    Function.prototype.call(thisArg[,arg1[,arg2…]]);

    从函数原型可以看到,第一个参数都被取名为thisArg,也就是说,所有函数内部的this
    指针都会被赋值为thisArg,这就达到了将函数作为另外一个对象的方法运行的目的。两个
    方法除了thisArg 参数,都是为Function 对象传递的参数。

     <script type="text/javascript">
            //定义一个函数func1,具有属性p和方法A
            function func1() {
                this.p = "func1-";
                this.A = function (arg) {
                    alert(this.p + arg);
                }
            }
            //定义一个函数func2,具有属性p和方法B
            function func2() {
                this.p = "func2-";
                this.B = function (arg) {
                    alert(this.p + arg);
                }
            }
            var obj1 = new func1();
            var obj2 = new func2();
            obj1.A("byA"); //显示func1-byA
            obj2.B("byB"); //显示func2-byB
            obj1.A.apply(obj2, ["byA"]); //显示func2-byA,其中[“byA”]是仅有一个元素的数组,下同
            obj2.B.apply(obj1, ["byB"]); //显示func1-byB
            obj1.A.call(obj2, "byA"); //显示func2-byA
            obj2.B.call(obj1, "byB"); //显示func1-byB
        </script>

    可以看出,obj1的方法A被绑定到obj2运行后,整个函数A的运行环境就转移到了obj2,
    即this指针指向了obj2。同样obj2 的函数B也可以绑定到obj1 对象去运行。代码的最后4
    行显示了apply和call函数参数形式的区别。
    与 arguments 的length属性不同,函数对象的还有一个参数相关的属性length,它表示
    函数定义时所指定参数的个数,而非调用时实际传递的参数个数。例如下面的代码将显示2:

    function sum(a,b){
    return a+b;
    }
    alert(sum.length);

    call,apply都是Function的原型的方法,其他function继承

    this

    和传统意义的面向对象的语言不同,JavaScript 中的this 指针是一个动态的变量,一个
    方法内的this指针并不是始终指向定义该方法的对象的,在上一节讲函数的apply和call方
    法时已经有过这样的例子。

     <script type="text/javascript">
           <!--
            //创建两个空对象
            var obj1 = new Object();
            var obj2 = new Object();
            //给两个对象都添加属性p,并分别等于1和2
            obj1.p = 1;
            obj2.p = 2;
            //给obj1添加方法,用于显示p的值
            obj1.getP = function () {
                alert(this.p); //表面上this指针指向的是obj1
            }
            //调用obj1的getP方法
            obj1.getP();
            //使obj2的getP方法等于obj1的getP方法
            obj2.getP = obj1.getP;
            //调用obj2的getP方法
            obj2.getP();
    //-->
        </script>

    从代码的执行结果看,分别弹出对话框1 和2。由此可见,getP函数仅定义了一次,在
    不同的场合运行,显示了不同的运行结果,这是有this指针的变化所决定的。在obj1 的getP
    方法中,this就指向了obj1 对象,而在obj2 的getP 方法中,this就指向了obj2 对象,并通
    过this指针引用到了两个对象都具有的属性p。
    由此可见,JavaScript 中的this 指针是一个动态变化的变量,它表明了当前运行该函数
    的对象。由this指针的性质,也可以更好的理解JavaScript中对象的本质:一个对象就是由
    一个或多个属性(方法)组成的集合。每个集合元素不是仅能属于一个集合,而是可以动态
    的属于多个集合。这样,一个方法(集合元素)由谁调用,this指针就指向谁。实际上,前
    面介绍的apply方法和call方法都是通过强制改变this指针的值来实现的,使this指针指向
    参数所指定的对象,从而达到将一个对象的方法作为另一个对象的方法运行的效果。

    this的范围

    var user={
    name:"jack", //定义了name属性,初始化为jack
    favoriteColor:["red","green","black","white"],//定义了颜色喜好数组
    hello:function(){ //定义了方法hello
    alert("hello,"+this.name);
    },
    sex:"male" //定义了性别属性sex,初始化为sex
    }
    user.hello();       //"hello,jack"
    var user={
    name:"jack", //定义了name属性,初始化为jack
    favoriteColor:["red","green","black","white"],//定义了颜色喜好数组
    hello:function(){ //定义了方法hello
    alert("hello,"+name);
    },
    sex:"male" //定义了性别属性sex,初始化为sex
    }
    user.hello();      //"hello,"
    name="hongda";
    var user={
    name:"jack", //定义了name属性,初始化为jack
    favoriteColor:["red","green","black","white"],//定义了颜色喜好数组
    hello:function(){ //定义了方法hello
    alert("hello,"+name);
    },
    sex:"male" //定义了性别属性sex,初始化为sex
    }
    user.hello();          //"hello,hongda"
      name = "hongda";
            var user = {
                name: "jack", //定义了name属性,初始化为jack
                favoriteColor: ["red", "green", "black", "white"], //定义了颜色喜好数组
                hello: function () { //定义了方法hello
                    name = "hongdadada";
                    alert("hello," + name);
                },
                sex: "male" //定义了性别属性sex,初始化为sex
            }
            user.hello();     //"hello,hongdadada"

    一个对象内部的方法调用该对象的属性时要指明this,该属性不是某个范围内的变量。

     function fun() {
                name = "hongdada";
                function show() {  //没有意义
                    alert(name);
                }
            }
            var f = new fun();
            console.dir(f);

     function fun() {
                this.name = "hongdada";
                this.show=function show() {
                    alert(name);
                }
            }
            var f = new fun();
            console.dir(f);

    function中没有this时,它就是个方法,只有有this时它才类似一个类

    传递给函数的隐含参数:arguments

    当进行函数调用时,除了指定的参数外,还创建一个隐含的对象——arguments。
    arguments是一个类似数组但不是数组的对象,说它类似是因为它具有数组一样的访问性质,
    可以用arguments[index]这样的语法取值,拥有数组长度属性length。arguments 对象存储的
    是实际传递给函数的参数,而不只局限于函数声明所定义的参数列表,

    function func(a,b){
    alert(a);
    alert(b);
    for(var i=0;i<arguments.length;i++){
    alert(arguments[i]);
    }
    }
    func(1,2,3);   //1,2,1,2,3

      代码:

     <script type="text/javascript">
            function dwn(s) {
                document.write(s + "<br/>");
            }
            //定义一个多边形(Polygon)类型
            function Polygon() {
                //存放多边形的顶点
                var m_points = [];
                m_points = Array.apply(m_points, arguments);
                //用上面介绍的那种方式定义getter
                function GETTER() { };
                GETTER.prototype = m_points[0];
                this.firstPoint = new GETTER();
                //公有属性
                this.length = {
                    valueOf: function () { return m_points.length },
                    toString: function () { return m_points.length }
                }
                //添加一个或多个顶点
                this.add = function () {
                    m_points.push.apply(m_points, arguments);
                }
                //取得序号为idx 的顶点
                this.getPoint = function (idx) {
                    return m_points[idx];
                }
                //设置特定需要的顶点
                this.setPoint = function (idx, point) {
                    if (m_points[idx] == null) {
                        m_points[idx] = point;
                    }
                    else {
                        m_points[idx].x = point.x;
                        m_points[idx].y = point.y;
                    }
                }
            }
            //构造一个三角形p
            var p = new Polygon({ x: 1, y: 2 }, { x: 2, y: 4 }, { x: 2, y: 6 });
            dwn(p.length);           //3
            dwn(p.firstPoint.x);     //1
            dwn(p.firstPoint.y);     //2
            p.firstPoint.x = 100; //不小心写了它的值
            dwn(p.getPoint(0).x); //1 不会影响到实际的私有成员
            delete p.firstPoint.x; //恢复
            dwn(p.firstPoint.x);    //1
            p.setPoint(0, { x: 3, y: 4 }); //通过setter 改写了实际的私有成员
            dwn(p.firstPoint.x); //3 getter 的值发生了改变
            dwn(p.getPoint(0).x);  //3
     
        </script>

    应用例子:

     function dwn(s) {
                document.write(s + "<br/>");
            }
            function App() {
            var fun={};
                var arr = Array.apply(null, arguments);
                var arr2 = Array.apply(arr2, arguments);
                var arr3 = Array.apply(fun, arguments);
                var arr4 = Array.apply(window, arguments);
                dwn(arr);
                dwn(arr2);
                dwn(arr3);
                dwn(arr4);
            }
            App(1, 2, 3, 4, 5, 6, 7, 8);

    Array这个function方法对象初始化中没有使用this,所有thisArg不管填什么都没影响。

       function Class1() {
                this.name = "class1";
                this.showNam = function () {
                    alert(this.name);
                }
            }
            function Class2() {
                this.name = "class2";
            }
            var c1 = new Class1();
            var c2 = new Class2();
            c1.showNam.call(c2);    //class2

    call也可以形成继承

       function Class1() {
                this.showTxt = function (txt) {
                    alert(txt);
                }
            }
            function Class2() {
                Class1.call(this);
            }
            var c2 = new Class2();
            c2.showTxt("cc");     //cc

    class2继承class1

    多继承

    function Class1() {
                this.showTxt1 = function (txt) {
                    alert("Class1:"+txt);
                }
            }
            function Class0() {
                this.showTxt0 = function (txt) {
                    alert("Class0:"+txt);
                }
            }
            function Class2() {
                Class0.call(this);
                Class1.call(this);
            }
            var c2 = new Class2();
            c2.showTxt0("cc");
            c2.showTxt1("cccc");

    在javascript框架prototype里就使用apply来创建一个定义类的模式

    var Class = {
      create: function() {
        return function() {
          this.initialize.apply(this, arguments);
        }
      }
    }

    解析:从代码看,该对象仅包含一个方法:Create,其返回一个函数,即类。但这也同时是类的
    构造函数,其中调用initialize,而这个方法是在类创建时定义的初始化函数。通过如此途径,
    就可以实现prototype中的类创建模式

      var vehicle=Class.create();
            vehicle.prototype = {
                initialize: function (type) {
                    this.type = type;
                },
                showSelf: function () {
                    alert("this vehicle is " + this.type);
                }
            }
    
    var moto=new vehicle("Moto");
    moto.showSelf();
  • 相关阅读:
    网易2019实习生招聘编程第3题——牛牛找工作
    Linux find、locate、whereis、which命令
    Linux 常用命令
    Java线程池
    java连接池的maxIdle该如何配置
    Idea和redis的坑
    微服务架构下分布式事务解决方案——阿里GTS
    spring管理bean的三种创建方式
    jvm内存过高及那些对象导致内存过高,那些对象不会被gc回收
    Java虚拟机 运行时数据区
  • 原文地址:https://www.cnblogs.com/hongdada/p/2853140.html
Copyright © 2020-2023  润新知