javascript 函数的参数和C++之类的强类型语言有很大的差别。下面详细介绍了 javascript 函数参数的主要特点,一起来看看吧,希望对大家
学习javascript
有所帮助。
显式参数和隐式参数
· 显式参数(Parameters)
// 函数定义的时候列出函数的显式参数function foo(parameter1, parameter2){}
· 隐式参数(Arguments):函数的隐式参数是函数调用时传递给函数真正的值。javascript 中的参数在内部是用一个数组来表示的,函数接收到的始终都是这个数组,而不关心数组中包含哪些参数,在函数体内可以通过 Arguments 对象来访问这个参数数组。
参数规则
· 函数定义时显式参数没有指定数据类型。
· 函数对隐式参数没有进行类型检测。
· 函数对隐式参数的个数没有检测。(隐式参数个数和显式参数个数可以不同)
默认参数
如果函数在调用时没有提供隐式参数(也就是没有参数),参数会默认设置为: undefined
一般是没有什么问题,但是建议最后为参数设置一个默认值:
function a(x){
if(x === undefined)
x=0;
}
或者:
function a(x){
x = x || 0;
}
Arguments 对象
如果函数调用的时候,传入的参数个数大于显式参数的个数,参数只能通过 Arguments 对象来调用。
Arguments 对象是 javascript 函数内置的对象,它包含了函数调用时传入的参数数组。通过 Arguments 对象可以很容易的对每个传入的参数进行操作:
function a(){
var m = arguments[0]; // 第一个传入的参数
var n = arguments[1]; // 第二个传入的参数,如果只传入一个参数,那么该值为 undefined
var l = arguments.length; // 该值对应的函数调用时传入参数的个数
var ll = a.length; // 该值对应的函数定义的参数个数
}
看起来 arguments 好像和数组一样,但是 arguments 是一个 object 对象,并不是数组,它是一个类数组对象,不能对它使用 push、join等方法。上面例子中的 arguments
中的 i 只是作为 arguments 对象的属性,并不能理解为数组的下标。
内部属性
·callee:arguments 对象有一个 callee 属性,该属性是一个指针,指向拥有这个 arguments 对象的函数。
下面是经典的阶乘函数:
function factorial(num){
if(num <= 1){
return 1;
}else{
return num * factorial(num - 1);
}
}
console.log(factorial(5));//120
但是,上面这个函数的执行与函数名紧紧耦合在了一起,可以使用 arguments.callee 可以消除函数解耦:
function factorial(num){
if(num <= 1){
return 1;
}else{
return num * arguments.callee(num - 1);
}
} console.log(factorial(5));//120
但在严格模式下,访问这个属性会抛出
TypeError 错误
function factorial(num){ 'use strict';
if(num <= 1){
return 1;
}else{
return num * arguments.callee(num - 1);
}
} //TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to themconsole.log(factorial(5));
这时,可以使用具名的函数表达式
var factorial = function fn(num){
if(num <= 1){
return 1;
}else{
return num * fn(num - 1);
}
};
console.log(factorial(5));//120
同步
在形参个数和实参相同时,arguments 对象的值和对应形参的值保持同步:
function a(m){
console.log(m,arguments[0]); // 1 1
arguments[0] = 2;
console.log(m,arguments[0]); // 2 2
m = 3;
console.log(m,arguments[0]); // 3 3
}
a(1);
注:虽然形参和对应 arguments 对象的值相同,但并不是相同的内存空间,它们是独立的内存空间,但是值会同步。
不过在严格模式下,它们的值是独立的:
function a(m){ 'use strict'; // 严格模式
console.log(m,arguments[0]); // 1 1
arguments[0] = 2;
console.log(m,arguments[0]); // 1 2
m = 3;
console.log(m,arguments[0]); // 3 2
}
a(1);
当形参没有对应实参的时候,arguments 对象的值和形参并不同步:
function a(m){
console.log(m,arguments[0]); // undefined undefined
arguments[0] = 2;
m = 3;
console.log(m,arguments[0]); // 3 2
}
a();
参数传递
javascript 中所有函数的参数都是按值传递的。也就是说,把函数外部的值复制到函数内部的参数,就和把值从一个变量复制到另一个变量一样。
· 基本类型:向参数传递基本类型的值时,被传递的值会被复制给一个局部变量。
· 引用类型:在向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化会反映在函数的外部,当在函数内部重写引用类型的形参时,这个变量引用的就是一个局部对象了。而这个局部对象会在函数执行完毕后立即被销毁。