JavaScript基础知识(二) arguments,with,caller,callee,call,apply,eval

上一篇中讲了有关prototype chain(原型链)的相关知识。在这个章节中,主要讲内置的参数,函数的用法。因为在学习《JavaScript设计模式》中很多次出现,如果只是浅显的了解,学习的过程中会有很多感觉很吃力的时候,所以,也花了些功夫从网上和书本上找了一些材料学习,算是有了点了解。从网上搜集的材料连接放在上一篇原型链的开头处,需要的同学自己去找吧。

Arguments

在讲arguments前,先明确一点:arguments是一个对象。

  1. function Sub(){
  2. }
  3. console.log(typeof Sub.arguments)

结果输出:object

Arguments是该对象正在执行的杆数和调用它的函数的参数。拿个例子来解释吧。

  1. function test(){
  2.   this.testArgument = function(){
  3.     for(var i=0;i<arguments.length;i++){
  4.       console.log("Argument "+i + ":"+ arguments[i]);
  5.     }
  6.     console.log("Argument length: "+ arguments.length);
  7.   }
  8. }
  9. var tmp = new test();
  10. tmp.testArgument("df","sdf");

结果输出:    

上述代码出现了很有意思的地方。我们没有定义testArgument(String str1,String str2)的方法,只定义了没有参数的testArgument()方法。原来javascript会自动忽略多出来的参数。而这些参数会保存在arguments对象中。记住,arguments对象的索引是从0开始滴。

With

这个关键子就是方便书写的意思。和java中的静态引入有点像,看例子:

  1. function testWith(){
  2.   this.a = 6;
  3.   this.b = "with";
  4. }
  5. var tmp = new testWith();
  6. with(tmp){
  7.   console.log(a);
  8.   console.log(b);
  9. }

从上面代码中可以看到,使用with之后,在代码体中不用写tmp.a,而直接使用a即可。是不是和java中的静态引入很像!

Caller

这个函数的意思就是,返回一个函数的引用,该函数调用了这个函数。可能光听解释不太明白,看代码:

  1. function callerDemo(){
  2.   if(callerDemo.caller){
  3.     var a = callerDemo.caller.toString();
  4.     console.log(a);
  5.   }else{
  6.     console.log("this is a top function");
  7.   }
  8. }
  9. (function call(){
  10.   callerDemo();
  11. })();

输出结果:

在代码中第三行,我们调用了toString方法,也就是说callerDemo.caller返回的是call()这个函数的引用。

可能有些同学看不明白()();的用法。这里简单解释一下,这里可以吧第一个()看作成一个匿名函数,暂且记作xx,第二个括号就是调用这个匿名函数,也就相当于xx();

Callee

这个函数有点不好理解。Callee是arguments的一个属性,这个属性返回的是这个函数的自身。Callee有一个属性length,为函数形参的长度。

形参:就是命名函数时定义的参数;实参:实际调用函数时的参数个数。直接看例子

  1. //用于验证参数
  2. function calleeLengthDemo(arg1, arg2) {
  3.     if (arguments.length==arguments.callee.length) {
  4.         console.info(typeof arguments.callee);
  5.         console.info(arguments.callee === calleeLengthDemo);
  6.         console.log("pass!");
  7.         return;
  8.      } else {
  9.          console.log("actual:" +arguments.length);        //实参的数目
  10.          console.log("defined: " +arguments.callee.length);    //形参的数目
  11.      }
  12. }
  13. (function(){
  14.   calleeLengthDemo(11,22);
  15.   calleeLengthDemo(11,22,33,44);
  16. })();
  17. //递归计算
  18. var sum = function(n){
  19.   if (n <= 0)
  20.   return 0;
  21.   else
  22.     return n + arguments.callee(n - 1)
  23. }
  24. console.log(sum(10));

这个例子分为两部分,第一部分1~16是说明arguments.callee.length代表的是什么,以及arguments.callee返回的就是该对象本身;第二部分17~24使用了一个递归的例子,说明这个函数的具体用法。

输出结果:

从结果中可以看出,callee的用法。返回结果true证明arguments.callee返回的就是其函数本身。arguments.callee的类型也是function类型。

Call,apply

  1. call([thisObj[,arg1[,arg2[,[,.argN]]]]])

光看这个可能看的不明白。上面call的用法就是:thisObj是必填项,arg是可选项,每一个参数必须是使用逗号分隔。thisObj如果填写null,将用Globe作用于指定。

这个函数的作用是什么呢?先看代码:

  1. function Base(){
  2.   this.a = 5;
  3.   this.b = "haha";
  4. }
  5.  
  6. (function Sub(){
  7.   this.c = "Hello";
  8.   Base.call(this);
  9.   console.log(this.a + " ||" +this.b + "||" + this.c);
  10. })();

输出结果:5 ||haha||Hello

Call函数的作用就是,将一个函数的作用域叠加于另一个函数上,在上述代码中Base.call(this)就是把Base的作用域叠加到this的作用于。所以在代码中第8行,this.a与this.b就只带的是Base.a与Base.b,而this.c输出Hello证明这个代码的作用是叠加关系

那既然是叠加,如果Base和Sub同时有相同的属性,该怎么执行呢?

  1. function Base(){
  2.   this.a = 5;
  3.   this.b = "haha";
  4.   this.c = 'Hello World';
  5. }
  6.  
  7. (function Sub(){
  8.   this.c = "Hello";
  9.   Base.call(this);
  10.   //this.c = "Hello";
  11.   console.log(this.a + " ||" +this.b + "||" + this.c);//结果输出5||haha||Hello World
  12. })();

结果输出:5||haha||Hello World

上面代码中可以看到,这个叠加也有一个先后顺序。Base.call(this)的作用相当于把Base中的代码复制到这块:

  1. function Base(){
  2.   this.a = 5;
  3.   this.b = "haha";
  4.   this.c = 'Hello World';
  5. }
  6.  
  7. (function Sub(){
  8.   this.c = "Hello";
  9.   //Base.call(this)开始
  10.   this.a = 5;
  11.   this.b = "haha";
  12.   this.c = 'Hello World';
  13.   //Base.call(this)结束
  14.   console.log(this.a + " ||" +this.b + "||" + this.c);
  15. })();

所以this.c='Hello World'这个语句吧第8行中的this.c='Hello'覆盖掉了。至于this.c最终等于什么,就看Base.call(this)调用的位置了。

Apply

  1. apply([thisObj[,argArray]])

这个函数的作用同call是一样的,只不过argArray参数是一个数组形式的,既可以直接把arguments当作参数传递,如果没有就有因个空数组代替

这里跟查的资料不一样,资料上说argArray是必选项,不然会抛出TypeError错误,但是我在node和IE浏览器中验证,这个argArray也是一个可选项

因为作用是相同的,所以在这里就不再重复的写一下代码了。下面介绍这里面的参数是怎么用的:

  1. function par(name,age){
  2.   this.parName = name;
  3.   this.parAge = age;
  4. }
  5. function child(chname,parname,parAge){
  6.   this.chName=chname;
  7.   par.apply(this,[parname,parAge]);
  8. };
  9.  
  10. var child=new child("john","Mr john","50");
  11. console.log(child.parName+";"+child.chName+ ";"+child.parAge);

结果输出:Mr john;john;50

上面代码中,定义了一个par函数,里面有parName和parAge,在代码第七行中使用了par.apply(this,[parname,parAge]);把parname,parAge参数传递给par函数。进行初始化。

当然也可以把arguments当作参数传递。Call中的参数用法和apply类似。不重复了。

eval

eval函数接受一个参数s,如果s不是一个字符串,直接返回s;否则执行s语句。如果s语句执行结果是一个值,则返回该值,否则返回undefined。

  1. var testEval_int = 5;
  2. var testEval_obj = {a:2};
  3. console.log(eval(testEval_int));
  4.  
  5. var testEval_str = "(function tmp(){this.a =5;this.b = 'haha';console.log(a + ':' + b);})();";
  6. eval(testEval_str);

输出结果:5:haha

原文地址:https://www.cnblogs.com/wenlonghor/p/3332004.html