zoukankan      html  css  js  c++  java
  • javascript下的arguments,caller,callee,call,apply示例及理解

    (参考:http://justcoding.iteye.com/blog/589111

    Arguments 
    该对象代表正在执行的函数和调用它的函数的参数。

     [function.]arguments[n]

    参数

    function :选项。当前正在执行的 Function 对象的名字。

    n :选项。要传递给 Function 对象的从0开始的参数值索引。


    说明 
    Arguments 是进行函数调用时,除了指定的参数外,还另外创建的一个隐藏对象。

    Arguments是一个类似数组但不是数组的对象,说它类似数组是因为其具有数组一样 的访问性质及方式,可以由arguments[n]来访问对应的单个参数的值,并拥有数组长度属性length

    还有就是arguments对象存储的是实际传递给函数的参数,而不局限于函数声明所定义的参数列表,而且不能显式创建 arguments对象。arguments对象只有函数开始时才可用。下边例子详细说明了这些性质:

    Js代码  

     1 <script type="text/javascript">  
     2     //arguments 对象的用法。  
     3     function ArgTest(a, b){  
     4         var i, s = "The ArgTest function expected 
    
    ";  
     5         var numargs = arguments.length; // 获取被传递参数的数值。  
     6         var expargs = ArgTest.length; // 获取期望参数的数值。  
     7   
     8         if (expargs < 2){  
     9             s += expargs + " argument. ";  
    10         }else{  
    11             s += expargs + " arguments. ";  
    12         }  
    13   
    14         s += "
    
    ";  
    15   
    16         if (numargs < 2){  
    17             s += numargs + " was passed.";  
    18         }else{  
    19             s += numargs + " were passed.";  
    20         }  
    21   
    22         s += "
    
    ";  
    23   
    24         for (i =0 ; i < numargs; i++){ // 获取参数内容。  
    25             s += " Arg " + i + " = " + arguments[i] + "
    ";  
    26         }  
    27   
    28         alert(s); // 返回参数列表。  
    29     }   
    30   
    31 ArgTest(1,2);  
    32   
    33 </script>  

    说明:function.length代表函数定义的参数个数,function.arguments.length函数实际传递的参数个数。

     在此添加了一个说明arguments不是数组(Array类)的代码:

     

    Js代码  

     1 <script type="text/javascript">  
     2     Array.prototype.selfvalue = 1;  //为数组添加属性
     3     alert(new Array().selfvalue);  
     4   
     5     function testAguments(){  
     6         alert(arguments.selfvalue);  //arguments不是数组所以没有selfvalue值
     7     }   
     8   
     9     testAguments()  
    10 </script>  

     

     运行代码你会发现第一个alert显示1,这表示数组对象拥有selfvalue属性,值为1,而当你调用函数testAguments时,你会 发现显示 的是“undefined”,说明了不是arguments的属性,即arguments并不是一个数组对象。 
    在此附加上大家推荐的一个简单方 法:

     

    Js代码  

    1 alert(arguments instanceof Array);  
    2 alert(arguments instanceof Object);  

    caller 

    返回一个对函数的引用,该函数调用了当前函数。

    functionName.caller  functionName对象是所执行函数的名称。

     

    说明 

    对于函数来说,caller 属性只有在函数执行时才有定义。如果函数是由顶层调用的,那么 caller 包含的就是 null 。

    如果在字符串上下文中使用 caller 属性,那么结果和 functionName.toString 一样,也就是说,显示的是函数的反编译文本。 

     

    下面的例子说明了 caller 属性的用法:

     

    Js代码  

     1 <script type="text/javascript">  
     2     // caller demo
     3     function callerDemo() {  
     4         if (callerDemo.caller) {  
     5             var a= callerDemo.caller.toString();  
     6             alert(a);  
     7         } else {  
     8             alert("this is a top function");  
     9         }  
    10     }  
    11   
    12     function handleCaller() {  
    13         callerDemo();  
    14     }   
    15   
    16     callerDemo();    //函数由顶层调用(运行一下试试,貌似结果有出入)
    17     handleCaller();  // 返回handleCaller()
    18 </script>   

     

    callee 

    返回正被执行的 Function 对象,也就是所指定的 Function 对象的正文。

     

    [function.]arguments.callee 
    可选项 function 参数是当前正在执行的 Function 对象的名称。

     

    说明 

    callee 属性的初始值就是正被执行的 Function 对象。 

    callee 属性是 arguments 对象的一个成员,它表示对函数对象本身的引用,这有利于匿名 函数的递归或者保证函数的封装性,例如下边示例的递归计算1到n的自然数之和。而该属性仅当相关函数正在执行时才可用。还有需要注意的是callee拥有length属性,这个属性有时候 用于验证还是比较好的。

     arguments.length是实参长度,arguments.callee.length形参长度,由此可以判断调用时形参长度是否和实参长度一致。 

     

    示例

    Js代码  

     1 <script type="text/javascript">  
     2     //callee可以打印其本身  
     3     function calleeDemo() {  
     4         alert(arguments.callee);  
     5     }  
     6   
     7     //用于验证参数  
     8     function calleeLengthDemo(arg1, arg2) {  
     9         if (arguments.length==arguments.callee.length) {  
    10             alert("验证形参和实参长度正确!");  
    11         } else {  
    12             alert("实参长度:" + arguments.length);  
    13             alert(" 形参长度: " + arguments.callee.length);  
    14         }  
    15     }  
    16   
    17     calleeDemo('1','2');  
    18     calleeLengthDemo('1','2');  
    19     calleeLengthDemo('1');  
    20   
    21     //递归计算  
    22     var sum = function(n){  
    23             if (1==n) {  
    24                 return 1;  
    25             }else{  
    26                 return n + sum (n-1);  // 修改为arguments.callee (n-1);
    27             }  
    28         }  
    29           
    30     alert(sum(100));   
    31   
    32 </script>  

     

    其中函数内部包含了对sum自身的引用,函数名仅仅是一个变量名,在函数内部调用sum即相当于调用 一个全局变量,不能很好的体现出是调用自身,这时使用callee会是一个比较好的方法。

     

    apply and call 
    它们的作用都是将函数绑定到另外一个对象上去运行(注意这样调用就直接运行函数了哟!)。

    两者仅在定义参数方式有所区别: 
    apply(thisArg, argArray); 
    call(thisArg[,arg1,arg2…] ]); 
    即 所有函数内部的this指针都会被赋值为thisArg,这可实现将函数作为另外一个对象的方法运行的目的。

     

    apply的说明 
    如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一TypeError。 
    如果没有提供 argArray 和 thisArg任何一个参数,那么 Global 对象将被用作 thisArg, 并且无法被传递任何参数。

     

    call 的说明 
    call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisArg指定的新对象。 
    如果没有提供 thisArg参数,那么 Global 对象被用作 thisArg

    相关技巧: 
    应用call和apply还有一个技巧在里面, 就是用call和apply应用另一个函数(类)以后,当前的 函数(类)就具备了另一个函数(类)的方法或者是属性,这也可以称之为继承。 看下面示例:

     

    Js代码  

     1 <script type="text/javascript">  
     2     // 继承的演示  
     3     function base() {  
     4         this.member = "dnnsun_Member";  
     5         this.method = function() {  
     6             window.alert(this.member);  
     7         }  
     8     }  
     9   
    10     function extend() {  
    11         base.call(this);  
    12         window.alert(member);  
    13         window.alert(this.method);  
    14     }   
    15   
    16     base();  
    17     extend();  
    18 </script>  

    上面的例子可以看出,通过call之后,extend可以继承到base的方法和属性。 
    顺便提一下,在javascript框架 prototype里就使用apply来创建一个定义类的模式, 

    其实现代码如下:

     

    Js代码 

     1 <script type="text/javascript">  
     2 var Class = {  
     3     create: function() {  
     4         return function() {  
     5             this.initialize.apply(this, arguments);  
     6         }  
     7     }  
     8 }   
     9   
    10 </script>   

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

    示例:

    Js代码  

     1  var vehicle=Class.create();  
     2     
     3  vehicle.prototype={  
     4       initialize:function(type){  
     5           this.type=type;  
     6      }  
     7    
     8      showSelf:function(){  
     9          alert("this vehicle is "+ this.type);  
    10      }  
    11  }  
    12    
    13  var moto=new vehicle("Moto");  
    14  moto.showSelf();   

     

    更详细的关于prototype信息请到其官方网站查看。 
    评论还有更精彩对此的理解,在这我就不再添加了,大家可以看看加深理解。 看完了上面的代码,就可以。

    下面的代码是给一些比较想立即看到效果的人看的(以上内容的代码合集)。多测试。

    Js代码  

      1 <script language="JavaScript">  
      2   
      3 /**//* 
      4 * 演示arguments的用法,如何获取实参数和形数数 
      5 */  
      6 function argTest(a,b,c,d){  
      7     var numargs = arguments.length; // 获取被传递参数的数值。  
      8     var expargs = argTest.length; // 获取期望参数的数值。  
      9   
     10     alert("实参数目为:"+numargs);  
     11     alert("形数数目为:"+expargs);  
     12     alert(arguments[0]);  
     13     alert(argTest[0]); //undefined 没有这种用法  
     14 }  
     15   
     16 //argTest(1,2)  
     17 //结果:实参数目为:2;形数数目为:4;1;undefined  
     18 //argTest(1,2,3,4,5)  
     19 //结果:实参数目为:5;形数数目为:4;1;undefined  
     20 /*总结:js参数传递不像c#等语法要求的必须与函数定义一致,可以根据应用不同增加或减少参数,极端情况可以不声明参数,如*/  
     21   
     22 var test = function(){  
     23     var a = 0;  
     24     var l = 0;  
     25     while(l<arguments.length){  
     26         a += arguments[l];  
     27         l++;  
     28     }  
     29     alert(a);  
     30 }  
     31 test();//0  
     32 test(1,2);//3  
     33   
     34   
     35 /**//* 
     36 * arguments不是数组(Array类) 
     37 */  
     38 Array.prototype.selfvalue = 1;  
     39 //此处就是为人诟病的渲染原声对象吧  
     40 function testAguments(){  
     41     alert("arguments.selfvalue="+arguments.selfvalue);  
     42 }  
     43   
     44 //alert("Array.sefvalue="+new Array().selfvalue);  
     45 /*上面的调用说明所有Array对象的selfvalue都等于1*/  
     46 //testAguments();  
     47 /*结果undefined说明 arguments并非Array类型*/  
     48 /**//* 
     49 * 演示函数的caller属性. 
     50 * 说明:(当前函数).caller:返回一个对函数的引用,该函数调用了当前函数 
     51 */  
     52   
     53 function callerDemo() {  
     54     if (callerDemo.caller) {  
     55         var a= callerDemo.caller.arguments[0];  
     56         alert(a);  
     57     } else {  
     58         alert("this is a top function");  
     59     }  
     60 }  
     61   
     62 function handleCaller() {  
     63     callerDemo();  
     64 }  
     65 //callerDemo();  
     66 //结果:this is a top function  
     67 //handleCaller("参数1","参数2");  
     68 // 结果:参数1  
     69 /*总结:caller应用于函数对象,可以取到上层调用的函数对象及参数 
     70 */  
     71 /**//* 
     72 * 演示函数的callee属性. 
     73 * 说明:arguments.callee:初始值就是正被执行的 Function 对象,用于匿名函数 
     74 */  
     75   
     76 function calleeDemo() {  
     77     alert(arguments.callee);  
     78 }  
     79   
     80 //calleeDemo();  
     81 //(function(arg0,arg1){alert("形数数目为:"+arguments.callee.length)})();  
     82 /*总结:可用于实现递归,如:*/  
     83 var i = 0;  
     84 var a = function(){  
     85     i += arguments[0];  
     86     if(i>100||i==0){  
     87         alert(i);  
     88     }else{  
     89         arguments.callee(i);  
     90     }  
     91 };  
     92 a(1);  
     93   
     94 //结果128,其实就是2的7次方  
     95   
     96 /**//* 
     97 * 演示apply,call函数的用法 
     98 * 说明:作用都是将函数绑定到另外一个对象上去运行,两者仅在定义参数方式有所区别: 
     99 * apply(thisArg,argArray); 
    100 * call(thisArg[,arg1,arg2…] ]); 
    101 * 即所有函数内部的this指针都会被赋值为thisArg 
    102 */  
    103   
    104 function ObjectA(){  
    105     alert("执行 ObjectA()");  
    106     alert(arguments[0]);  
    107     this.hit=function(msg){alert(msg)}  
    108     this.info="我来自ObjectA";  
    109 }  
    110   
    111 function ObjectB(){  
    112     alert("执行 ObjectB()");  
    113     //调用ObjectA()方法,同时ObjectA构造函数中的所有this就会被ObjectB中的this替代  
    114     ObjectA.apply(this,arguments);//ObjectA.call(this);  
    115     alert(this.info);  
    116 }  
    117   
    118 //ObjectB('参数0');  
    119 /*总结:通常同callee联用*/  
    120 var i = 0  
    121 function a(b){  
    122     i++;  
    123     if(i>4){  
    124         return i;  
    125     }else{  
    126         return arguments.callee.call(this,b);  
    127     }  
    128 }  
    129 alert(a(0));  
    130   
    131 //讲述this作用域的问题  
    132 var value="global 变量";  
    133 function Obj(){  
    134     this.value="对象!";  
    135 }  
    136   
    137 function Fun1(){  
    138     alert(this.value);  
    139 }  
    140 //Fun1();  
    141 //结果:global 变量  
    142 //Fun1.apply(window);  
    143 //结果:global 变量,默认this=window  
    144 //Fun1.apply(new Obj());  
    145 //结果:对象,this=new Obj();Obj中的this指的是函数对象实例  
    146   
    147 </script>   

    apply,call函数的用法 

    Js代码  

     1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">  
     2 <html>  
     3 <head>  
     4 <script language="JavaScript">  
     5 <!--   
     6  /**  
     7   * 演示apply,call函数的用法  
     8   * 说明:作用都是将函数绑定到另外一个对象上去运行,两者仅在定义参数方式有所区别:  
     9   * apply(thisArg,argArray); 
    10      * call(thisArg[,arg1,arg2…] ]); 
    11      * 即所有函数内部的this指针都会被赋值为thisArg  
    12   */   
    13     
    14   function ObjectA(){   
    15   alert("执行ObjectA()");  
    16   alert(arguments[0]);  
    17   this.hit=function(msg){alert(msg)}   
    18   this.info="我来自ObjectA"   
    19   }   
    20     
    21   function ObjectB(){   
    22   alert("执行ObjectB()");  
    23   //调用ObjectA()方法,同时ObjectA构造函数中的所有this就会被ObjectB中的this替代   
    24   ObjectA.apply(this,arguments);//ObjectA.call(this);  
    25   alert(this.info);  
    26   this.hit("来自A的hit函数");  
    27  }   
    28    
    29  /**  
    30   *当ObjectB()函数中第三行为这样时:  
    31   *ObjectA.apply(this,arguments); 
    32   *下面的调用,依次打印:  
    33   * "执行ObjectB()"  
    34   * "执行ObjectA()"  
    35   * "参数0"  
    36   * "我来自ObjectA"  
    37   * "来自A的hit函数"  
    38   *-----------------------------------  
    39   *当ObjectB()函数中第三行为这样时:  
    40   *ObjectA.call(this); 
    41   *下面的调用,依次打印:  
    42   * "执行ObjectB()"  
    43   * "执行ObjectA()"  
    44   * "undefined"  
    45   * "我来自ObjectA"  
    46   * "来自A的hit函数"  
    47   */   
    48   ObjectB('参数0');  
    49 //-->  
    50 </script>  
    51 </head>  
    52 <body>  
    53 </body>  
    54 </html>  
  • 相关阅读:
    rsync--数据镜像备份_转
    netcat
    tcpdump抓包
    find命令应用exec及xargs
    traceroute/tracert--获取网络路由路径
    TCP/IP各层协议数据格式
    (转)mq经验总结-转
    (转)WebSphere MQ基础命令
    MQ通道搭建以及连通性检查
    (转)java并发之CountDownLatch、Semaphore和CyclicBarrier
  • 原文地址:https://www.cnblogs.com/ttcc/p/3748977.html
Copyright © 2011-2022 走看看