函数的实参和形参
JavaScript 中的函数定义并未指定函数形参的类型,函数调用也不对传入的实参做类型检查,实际上,JavaScript 甚至不检查传入形参的个数。
可选形参
当调用函数时传入的实参比函数声明时指定的形参个数少时,剩下的形参都将设置为 undefined
,为了更好地做到兼容性,应当给省略的参数赋一个合理的默认值:
function getPropertyNames(o, a = []) {
a = a || [];
for (var prop in o) a.push(prop);
return a;
}
注:可选形参要放到形参列表最后。
可变长的实参列表:实参对象
当调用函数时传入的实参个数超过函数定义时的形参个数时,可以通过参数对象来解决,在函数体内,标识符 arguments
是指向实参对象的引用,实参对象是一个类数组对象,这样通过数字下标就可以访问传入函数的实参值,而不是非要通过形参名来获取,比如我们来看一个返回传入数字最大值的示例:
通过上面两个特性,可以得出这样的结论:JavaScript 默认行为支持实参个数与形参个数不一致,如果小于的话,多出来的形参值都是 undefined
,如果大于的话会忽略多出来的实参,如果要获取的话可以通过 arguments
数组访问。
注:
arguments
是实参对象而不是真正的数组,此外用到arguments
访问实参的函数传入的实参个数不能为零。
除了数组元素,实参对象还定义了 callee
和 caller
属性(在 ECMAScript 5 严格模式下不支持这两个属性的读写操作),callee
属性用于指代当前正在执行的函数,caller
属性用于指代调用当前正在执行函数的函数,因此,通过 caller
属性可以访问调用栈。callee
属性也有其用武之地,比如在匿名函数中递归调用自身:
var factorial = function(x) {
if (x <= 1) return 1;
return x * arguments.callee(x-1);
}
将对象属性用作实参
为了避免函数形参太多,给调用和可读性带来困难,可以将参数以对象属性的方式传入和调用:
function easy_copy(args) {
var from = args.from;
var to = args.to;
}
实参类型
JavaScript 方法的形参并未声明类型,实参传入函数之前也未做任何类型检查。和 PHP 一样,我们只能在代码真正执行之前对参数作必要的检查,以避免运行时出错:
function sum(a) {
if (Array.isArray(a)) {
var total = 0;
for (var i = 0; i < a.length; i++) {
var element = a[i];
if (element == null)
continue;
if (isFinite(element))
total += element; // 有限数字
else
throw new Error('sum(): elements must be finite element');
}
}
throw new Error('sum(): argument must be array');
}
No Comments