javascript 中函数参数的理解

 
一。理解参数


    ECMASCript 函数的参数与大多数其他语言中的函数的参数有所不同,ECMAScript函数不介意参数传递进来多少个参数,也不在乎传进来参数是什么数据类型。也就是说,即便你定义的函数接收两个参数,在调用这个函数时也未必一定要传递两个参数。可以传递一个,三个甚至不传参数,二解释器永远不会有什么怨言。之所以会这样,原因是ECMASCript中的参数在内部是用一个数组来表示的。函数接收到始终都是这个数组,而不关心数组中包含哪些参数(如果有参数的话)。如果这个数组中不包含任何元素,无所谓; 如果包含多个元素,也没问题。实际上,在函数体内可以通过arguments对象来访问这个参数数组,从而获取传递给函数的每一个参数。

    其实,arguments对象只是一个与数组类似(它并不是Array的实例),因为可以使用方括号语法访问它的每一个元素(即第一个元素师arguments[0],第二个元素师arguments[1],一此类推),使用length 属性来确定传递进来多少个参数。在下面的(例1)中,sayHi()函数的第一个参数的名字叫name,而该参数的值也可以通过访问argumens[0]来获取,因此,那个函数也可以向下面(例2)这样重写,即不显示地使用命名参数: 例1和例2的效果是一样的。

      

 function sayHi(name, message) {
  alert("Hello "+ name + "," + message);
}   
例1
 
 function sayHi() {
  alert("Hello "+arguments[0] + "," +message);
}
例2
   例1重写后的函数例2中不包含命名参数。虽然没使用name和message标示符,但函数的功能依旧。这个事实说明ECMAScript函数的一个重要特点 : 命名参数只提供便利,但不是必需的。另外,在命名参数方面,其他语言可能需要事先创建一个函数签名,而将来的调用必须与改签名一致。但在ECMAScript中,没有这些条条框框,解析器不会验证命名参数。

   通过访问arguments对象的length属性可以获知有多少个参数传递给了函数。下面这个函数会在每次调用时,输出传入其中的参数个数:

 

 function howManyArgs() {
  alert("输出: "+arguments.length);
}
howManyArgs("string", 45); //输出:2
howManyArgs();  //输出:0
howManyArgs(23); //输出:1

再有如下这个例子:

 function doAdd() {
   if (arguments.length == 1){
    alert(arguments[0]+10);
    } else if (arguments.length == 2) {
        alert(arguments[0]+arguments[1]);
  }
}

doAdd(10);    //输出10
doAdd(20,20);  //输出40

   另一个与参数相关的重要的方面,就是arguments对象可以与命名参数一起使用,如下例子所示:

 function doAdd(num1, num2) {
  if (arguments.length == 1) {
    alert(num1+10);
 } else if (arguments.length == 2) {
  alert(arguments[0]+num2);
 }
}
  在重写后的这个doAdd()函数中,两个命名参数都与arguments对象一起使用。由于num1的值与arguments[0]的值相同,因此他们可以互换使用,(当然,num2和arguments[1]也是如此).

  arguments的值与对应命名参数的值保持同步。例如:

  例3:

 function doAdd(num1,num2) {
    arguments[0] = 10;
    alert(num1 + arguments[1]);
}
doAdd(3,10);  //输出 20
        每次执行这个doAdd()函数都会重写第二个参数,将第二个参数的只修改为10,。因为arguments对象中的值会自动反映到对应的命名参数,所以修改arguments[0],也就修改了num1, 结果他们的值都变成了10,。不过,这并不是说读取这两个值会访问相同的内存空间;他们的内存空间是独立的,但他们的值会同步。但这种影响是单向的;修改命名参数不会改变arguments中对应的值。另外还要记住,如果只传入一个参数,那么为arguments[1]设置的值不会反应到命名参数中。这是因为arguments对象的长度是由传入的参数个数决定的,不是由定义函数时的命名参数的个数决定的。

     关于参数还要记住最后一点: 没有传递值的命名参数将自动被赋予undefined值、这就跟定义了变量但没有初始化一样。

     严格模式对如何使用arguments对象做出了一些限制,首先,向前面(例3)中的那样赋值会变得无效,也就是说,即使把arguments[0] = 10, num1的值仍然还是undefined. 其次,重写arguments的值会导致语法错误。

     ECMAScript中的所有参数传递的都是值,不可能通过引用传递参数.

   

.ECMAScript 函数没有重载

         ECMAScript函数不能像传统意义上那样实现重载。而在其他语言(如:java)中,可以为一个函数编写两个定义,只要这两定义的签名(接受的参数的类型和数量)不同即可。如前所述,ECMAScript函数没有签名,因为其参数是由包含零个或多个值的数组表示的。(其实也可这么理解,函数的参数的个数或类型是不确定的,由传入的参数个数决定的,所以当传入实参时解释器不知道该调用哪个重载函数)而没有函数签名,真正的重载是不可能做到的。

      如果在ECMAScript中定义了两个名字相同的函数,则该名字只属于后定义的函数,请看下面的例子:

 

 function addSomeNumber(num) {
 return num+100;
}
function addSomeNumber(num) {
 return num+200;
}
var result = addSomeNumber(100);  //输出: 300

   在此,函数addSomeNumber(num) 被定义两次。由于后定义的函数覆盖了先定义的函数,因此当调用函数时,返回的结果就是300.

 

原文来自 :JavaScript 高级程序设计(第三版)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值