JS中函数的参数
参数不是必需的
在JS函数中,通常要通过参数来传递数据。但是JS和其他编程语言不一样的地方在于,JS并不在乎你传递的参数个数及类型;换句话说,即使你定义函数时只接收2个参数,在实际调用时你可以传递1个参数,3个参数甚至多个参数都无所谓,原因就在于ES函数中的参数在内部其实是用一个数组来表示,我们通常使用arguments
这个对象来访问传递到函数中的每一个参数。
arguments对象
arguments
对象其实是一个类数组对象,与JS中的数组有很多类似地方,我们可以使用方括号语法来访问arguments
对象的数据(例如使用arguments[0]
来访问第一个参数,arguments[1]
来访问第二个参数等);因此使用arguments
对象我们甚至可以在定义函数时不使用命名参数(不推荐但的确可以)。例如:
function sayHi(name,message) {
alert("Hello " + name + "," + message);
}
对于该函数我们可以使用arguments对象
改写:
function sayHi() {
alert("Hello " + arguments[0] + "," + arguments[1])
}
改写后的函数功能与之前完全一样,这个事实说明了ES函数的一个重要特点:命名的参数提供便利,但不是必需的。
length属性
arguments
对象的length
属性返回实际调用时传递的参数个数,注意:是实际调用时传递的参数个数,即实参。
function howManyArgs() {
return arguments.length;
}
howManyArgs(1);//1
howManyArgs("hello","world");//2
howManyArgs("123","hello",false,12);//4
与实参相对于的是形参,即定义函数时的命名参数。如果想要获得一个函数的形参个数,可以使用函数的length
属性(函数也是对象,因此也具有属性和方法)。
function howManyArgs() {
return arguments.length;
}
console.log(howManyArgs.length);//0
function doAdd(num1,num2) {
alert(num1+num2);
}
console.log(doAdd.length);//2
一句话总结:函数的length
属性返回形参格式,而arguments
对象的length属性则返回实参个数。
注意点
1、arguments
对象可以和命名参数一起使用
这个很容易理解,因为arguments[0]
其实就是第一个参数,arguments[1]
是第二个参数,因此可以相互替换使用。例如:
function doAdd(num1, num2) {
if(arguments.length === 1){
alert(num1 + 10);
} else if (arguments.length === 2){
alert(arguments[0] + num2);
}
}
2、arguments的值永远与对应命名参数的值保持同步
看下面的例子:
function doAdd(num1, num2) {
arguments[1] = 10;
alert(arguments[0] + num2);
}
执行doAdd()函数,将会重写num2的值,因为修改arguments
对象中的值会自动反映到对应的命名参数中。
但是需要注意的是:arguments对象中的值和命名参数的值占据相互独立的内存空间,只是值同步而已。
同时,我们说arguments
对象中的值是实参,这也就意味着当给doAdd()函数仅传入一个参数时,arguments[1]的值不会反映到命名参数中,原因就在于arguments对象的长度是有实际调用时传入的参数个数决定的,而不是由定义时的命名参数的个数决定的。
3、严格模式下的限制
严格模式下对arguments对象的使用作出了一定限制。主要体现在:
- 对arguments对象中的值重新赋值不会同步到参数中
- 重写arguments的值会导致语法错误(代码将不会执行)
例如:
function doAdd(num1,num2) {
"use strict";
arguments[1] = 10;//严格模式下赋值不会同步到参数中
console.log(arguments[0] + num2);
}
doAdd(12,15);//27
因此,除非有必要,否则我们不推荐在函数内部使用arguments来重写实参的值。