函数的形参和实参:
参数有形参(parameter)和实参(argument)的区别,形参相当于函数中定义的变量,实参是在运行时的函数调用时传入的参数。
ECMAScript函数的参数与大多数其他语言中函数的参数有所不同。ECMAScript中的函数定义并未指定函数形参的类型,函数调用也未对传入的实参值做任何类型检查,甚至不检查传入形参的个数;也就是说,即便定义的函数只接收两个参数,在调用 这个函数时也未必一定要传递两个参数,可以传递一个、三个甚至不传递;在实际场景中,需要处理当调用函数时的实参个数和声明的形参个数不匹配的情况,也会测试函数的实参的类型,以避免非法的实参传入函数;
可选形参:
当实参比形参的个数要少时,剩下的形参都将设置为undefined值;为了让实参与形参保持较好的适应性,有必要为可选形参设置一个合理的默认值;如:


形参个数:
函数本身的length属性,只读,它代表函数的形参个数,即函数期望传入的实参个数,如:
function sum(a,b,c){
console.log(sum.length); // 3
}
sum();
console.log(sum.length); // 3
实参对象(arguments):
ES函数的参数有自己独特的特点,即当调用函数时传入的实参个数超过函数定义的形参个数时,没有办法直接获得超出的实参的值,但可以使用实参对象arguments来获取;
在函数体内,arguments是指向实参对象有的引用,其是一个类数组对象(应该是一个集合);函数接收的始终都是这个数组,而不关心数组中包含哪些参数;即使没有传递参数,这个数组也存在,只不过是包含0个元素的数组;
function func(a,b){
console.log(arguments);
}
func();
func(1,2,3,4,5);
arguments对象只是与数组类似,它并不是Array的实例;可以使用方括号语法访问它的每一个元素(即第一个元素是arguments[0],第二个元素是arguments[1],以此类推),使用length属性来确定传递进来多少个参数,即length属性说明调用函数时实际传递的参数个数;;
如,不显式地使用命名参数:
function sayHi(){
console.log("传入了:" + arguments.length + "个参数");
console.log("Hello,"+arguments[0]+","+arguments[1]);
}
//sayHi();
sayHi("wangwei","欢迎你来学习");
说明:在ECMAScript中,命名的参数只提供便利,但不是必需的;另外,在命名参数方面,其他语言可能需要事先创建一个函数签名,而将来的调用必须与该签名一致;但在ECMAScript中,没有这些规定,解析器不会验证命名参数,因此可以使用arguments对象来验证所传递的参数是否符合函数要求;如:

说明:在某些时候,没有必要检查实参的个数,因为JS的默认行为是可以满足需要的,如省略的实参都是undefined,多出的参数自动省略。
验证形参与实参的个数,如:

// 根据实参,返回最大值
function max(/* ... */){
var max = Number.NEGATIVE_INFINITY;
for(var i = 0; i< arguments.length;i++)
if(arguments[i] > max) max = arguments[i];
return max;
}
var largest = max(1,10,100,2,3,1000,4,5,10000,6);
console.log(largest); // 10000
类似于这种可以接收任意个数的实参,这种函数也被称为“不定实参函数”,这个术语来自C语言。
但真正的不定实参的个数不能为零,其应用的场景是:该函数包含固定个数的命名和必须的参数,以及随后个数不定的可选实参,即arguments对象可以与命名参数一起使用;

arguments并不是真正的数组,它是一个对象,其数组元素是函数实参的别名;arguments的值永远与对应命名参数的值保持同步;

注:在严格模式下,重写arguments的值会失效,但不会导致语法错误;
实参类型:
Javascript是一门弱类型语言,所以函数中的形参并没有类型声明,并且在传入参数前也未做任何类型检查,虽然JS可以进行数据类型的自动转换,但在某些时候(类型不同,不会导致语法错误,但在程序运行时有可能导致错误),函数还是希望得到一个类型明确的参数值,此时,应当对所传入的参数进行类型的检查,如:


ECMAScript函数不能像传统意义上那样实现重载;而在其他语言中,可以为一个函数编写两个定义,只要这两个定义的签名(参数的类型和数量)不同即可;ECMAScript函数没有签名,因为其参数是由包含零或多个值的数组来表示的;而没有函数签名,真正的重载是不可能做到的;
如果定义了两个名字相同的函数,则只有后定义的有效,如:
function show(){alert("ok")};
function show(){alert("wangwei")};
show();
说明:即是第二个把第一个覆盖了;
var addNum = function(num){return num + 100;};
addNum = function(num){return num + 200;};
模拟重载:可以通过检查传入函数中参数的类型和数量并作出不同的反应,可以模拟方法的重载;

arguments对象除了拥有数组元素外,还定义了callee和caller属性;
callee属性指向当前正在执行的函数,在某些时候非常有用,如在一个匿名函数中使用递归;但在严格模式下会抛出错误,所以,尽量避免使用callee属性,可以为函数明确定义一个名称;

将对象用做实参:
可以采用将对象作为实参,该对象的属性就是实际需要的实参值,并且参数的顺序就无关紧要了,而且还可以方便的设置缺省参数的默认值;作为实参的对象,一般采用键/值对的方式进行定义;如:
