• 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

  • 相关阅读:
    SpringBoot配置文件
    SpringBoot基础开发流程
    day06-01数字类型、数字类型的转换
    特有的循环结构(for-else、while-else)——Python篇
    分支、循环——Python基础篇
    循环关键字——Python篇
    另类三目运算符——Python篇
    原码、反码以及补码
    Python运算符
    Python变量
  • 原文地址:https://www.cnblogs.com/wenlonghor/p/3332004.html
Copyright © 2020-2023  润新知