javascript中call,apply,arguments,callee,caller的用法

<%@ page language="java" import="java.util.*" pageEncoding="gbk"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    <!-- 
    apply call 方法,是javascript 实现类继承重要的内容,也是原型链的重要内容;
    javascript 的基础, javascript 原型链
    javascript中call、apply、argument、callee、caller
    call 方法: call 调用一个对象的一个方法,以另一个对象替换当前对象;
    call([thisObj[,arg1[,arg2[,[....argN]]]]])
    
    参数:
    thisObj 可选项,将被用作当前对象的对象;
    arg1, arg2, arg3,....argN 可选择项,将被传递方法参数序列;
    
    说明:
    call 方法可以用来代替另一个对象[构造函数]调用一个方法,call 方法可以将一个函数的对象上下文从初始的上下文改变
    为由 thisObj 指定的新对象;
    如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj;
     -->
     <script type="text/javascript">
      function person(name, age, sex) // javascript 构造函数
      {
        this.name = name;
        this.age = age;
        this.sex = sex;
      }
     
      function student(name, age, sex, universtiy, major)
      {
        this.universtiy = universtiy;
        this.major = major;
        person.call(this, name, age, sex); // person.call(student, argments....)
      }
     
     var john = new student("john", 20, "male", "MIT", "webdeveloper"); // 添加实例
     // alert(john.name + ' is ' +  john.age); // john is 20
     // 从上面的函数来看, 按理说 student 并没有 age 这个属性,但是为什么john.age 会是 20 呢?
     // 原因就是person.call(student, name, age, sex);从结果来看, call 多少有点继承的味道;
     // A.call(B, argument, argument2 ....) 结果就是B 继承了A,对 B进行实例化后,B 里面继承了A的属性和方法;
     
     function person2(name, age, sex)
     {
       this.name = name;
       this.age = age;
       this.sex = sex;
       this.say = function(){alert("my name is " + name);};
     }
     
     function student2(name, age, sex, university, major)
     {
       this.universtiy = university;
       this.major = major;
       person2.call(this, name, age, sex);
     }
     
     var cathy = new student2("cathy", 20, "male", "MIT", "webdeveloper");
     alert(cathy.age + ', she major in  ' + cathy.major);
     cathy.say();
     
     // 只有"方法"才能使用call 方法,其他对象或属性没有,这里指的方法 即:typeof(any) == 'function'
     // 其它typeof 非function 的都没有call 方法,比如 Array 数组就没有call 方法
     // 当然, call 方法不是必须在构造函数体内:
     function person3(name, age, sex)
     {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.say = function() {alert("my name is "+ this.name);};
     }
     
     function student3(name, age, sex, university, major)
     {
       this.name = "inner";
       this.university = university;
       this.major = major;
     }
     
     var john = new student3("john", 20, "male", "MIT", "webdeveloper");
     var person3 = new person3();
     person3.say.call(john); // my name is inner []
     
     // 同时继承多个类[javascript 构造函数]
     function parent(father, mother)
     {
        this.father = father;
        this.mother = mother;
        this.tell = function() {alert(this.father + " ," + this.mother);};
     } 
     
     function person4(name, age, sex)
     {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.say = function () {alert("my name is " + this.name);};
     }
     
     function student4(name, age, sex, university, major)
     {
       this.name = "inner";
       this.university = university;
       this.major = major;
       parent.call(this);
       person4.call(this, name, age, sex);
     }
     
     var michael = new student4("michael", 20, "male", "MIT", "webdeveloper");
     alert(michael.sex);
     michael.father = "Bob Micheal";
     michael.mother = "Mary michal";
     michael.tell();
     
     // 通过parent.call(this);person.call(this); student同时继承了parent和person的属性及方法
     // apply 方法,应用某一个对象的一个方法,用一个对象替换当前对象;
     // 语法: apply([thisObj[,argArray]])
     // 参数 thisObj 可选项,将被用作当前对象的对象;
     // argArray 可选项,将被传递给该函数的参数数组;
     // 说明:
     // 如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个TypeError;
     // 如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj 并且无法传递任何参数
     // apply 方法与 call 的区别在于,call 传递参数直接列出来就可以了,而apply 传递的参数需要把参数放在数组里面;
     function person6(name, age, sex)
     {
       this.name = name;
       this.age = age;
       this.sex = sex;
       this.say = function(){alert("my name is " + this.name);};
     }
     
     function student6(name, age, sex, university, major)
     {
       this.university = university;
       this.major = major;
       person6.apply(this, [name, age, sex]); //apply与call的区别,传递参数的方法不同
     }
     
     var jimmy = new student6("jimmy", 20, "male", "MIT", "webdeveloper");
     alert(jimmy.sex);
     jimmy.say();
     
     // argument 对象
     // argument 是javascript 的内置对象,它代表正在执行的函数和调用它的函数的参数;
     // 使用方法:[function[.arguments][n]]
     // 其中 function 是可选项,当前正在执行的 Function 对象的名字;
     // n 是必选项,要传递 Function 对象的从 0开始的参数值索引
     // 不能显示创建 arguments 对象,arguments 对象只有函数开始才可以使用,函数 arguments 对象并不是一个数组
     // 访问单个参数的方法与访问数组元素的方式相同,索引n 实际上是 arguments 对象 0...n 属性中其中一个参数..
     // 加载自调用函数--> arguments 在 javascript 关键字
     (function argTest(a, b, c, d) {
       alert("函数需要" + argTest.length +"个参数"); // 反馈 javascript 函数参数的个数
       alert("已经传入的参数为:" + arguments.length + "个");
       for (var i = 0; i < arguments.length; i++)
       {
         document.writeln(arguments[i]);
       }
     })(1,2,3,4);
     
     // callee 属性; callee 属性是arguments 的一个属性,返回方法的正文:
     // func.arguments.callee = func;
     (function argTest(a,b,c,d){  
	    alert("函数需要 "+argTest.length+" 个参数");  
	    alert("已经传入的参数为:"+arguments.length+"个");  
	    document.writeln("参数分别为:");  
	    for(var i=0;i<arguments.length;i++){  
	        document.writeln(arguments[i]);  
	    }  
         alert(arguments.callee); //增加此句,将alert显示出整段代码  
         })(1,2,3,4);  
     
     
     // callee 为arguments 属性,返回整个代码,可以轻松实现递归调用
     function fact(n)
     {  
	    if(n<=0){  
	        return 1;  
	    }else{  
	        return n*arguments.callee(n-1);  //轻松实现递归调用  
	    }  
     }  
     alert(fact(5)); // 求阶乘
     
     // caller 方法:
     // caller 属性是方法的一个属性,返回当前调用该方法的方法;
     // 如果在A 方法中调用了B 方法, 在A 方法执行的过程中,在B 函数中存在B.caller 等于A 的方法体;
     // 说明
     // 对于函数来说,caller 属性只有在函数执行时才有定义,假如函数是由顶层调用的,那么 caller 
     // 包含的就是 null,假如在字符串上下文中使用 caller 属性,那么结果和 functionName.toString 相同,也就是说,
     // 显示的是函数的反编译文本;
     function callerDemo()
     {
       if (callerDemo.caller)
       {
         var a = callerDemo.caller.toString();
         alert(a);
       }
       else
       {
          alert("this is a top function");
        }
     }
     function handleCaller() 
     {  
       callerDemo();  
     }  
		handleCaller(); //返回handleCaller方法体  
		callerDemo();  //返回this is a top function 
     
     </script>
  </head>
  
  <body>
    
  </body>
</html>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值