javascript函数参数
js函数参数有显式参数(Parameters)即形参和隐式参数(Arguments)实参
1、显式参数(Parameters)即形参在函数定义时列出。
function functionName(parameter1, parameter2, parameter3){ //要执行的代码 }
2、隐式参数(Arguments)即实参在函数调用时传递给函数的真正的值
function add(){ console.log(arguments[0], arguments[1], arguments[2]); }
add(1,2,3);//1 2 3
参数的个数
(1)当实参比比函数声明指定的形参个数少时,剩下的形参都将设置为undefined。
例:
function add(x, y){ console.log(x, y); } add(1);//1, undefined
(2)当实参比形参个数要多时,剩下的实参没办法直接获得,可以通过arguments对象来访问。在javascript中函数的参数在函数内部是用一个数组表示的。函数接收的始终都是这个数组,并不关心数组中包含哪些参数。而arguments是一个类数组对象,可以使用方括号语法来访问它的每一个元素。
例:
function add(x, y){ console.log(arguments[0], arguments[1], arguments[2]); } add(1, 2, 3);//1 2 3
arguments对象的length属性可以显示实参的个数,函数的length属性则显示形参的个数。
例:
function add(x, y){ console.log(arguments.length);//3 } add(1, 2, 3); console.log(add.length);//2
形参可以提供便利,但不是必须的。
function add(){ console.log(arguments[0] + arguments[1]); } add(1, 2);//3
实参与形参同步
当形参与实参个数相同时,arguments对象的值和对应形参的值保持同步,但命名空间独立。
例:
function test(num1, num2){ console.log(num1, arguments[0]);//1 1 arguments[0] = 2; console.log(num1, arguments[0]);//2 2 num1 = 10; console.log(num1, arguments[0]);//10 10 } test(1);
在严格模式下,arguments对象的值和形参都是独立的。
例:
function test(num1, num2){ 'use strict'; console.log(num1, arguments[0]);//1 1 argument[0] = 2; comnsole.log(num1, arguments[0]);//1 2 num1 = 10; console.log(num1, arguments[0]);//10 2 } test(1);
当形参并没有对应的实参时,arguments对象的值与形参的值并不对应。
例:
function test(num1, num2){ console.log(num1, arguments[0]);//undefined, undefined num1 = 10; arguments[0] = 5; console.log(num1, arguments[0]);//10, 5 } test();
对象参数:当一个函数包含超过3个形参时,要记住调用函数中实参的正确顺序是一件很繁琐的事情,可以通过值对的形式来传入参数。
参数的传递
javascript中所有函数的参数都是按值传递的。也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样,当传递的值是基本类型时,复制的是值本身。而参数为引用类型时,会把这个值在内存中的地址复制给一个局部变量。
(1)基本类型值的传递(传递的值是变量值的副本。)
在向参数传递基本类型的值时,被传递的值会被复制给一个局部变量(命名参数或arguments对象的一个元素)。
function add(num){ num += 10; return num; } var count = 20; console.log(add(count));//30 console.log(count);//20
(2)引用类型值的传递(传递的值是一个指向对象的指针。)
在向参数传递引用类型的值时,会把存储在变量对象中的值复制一份放到为新变量分配的空间中。不同的是,这个值的副本实际上是一个指针,而这个指针指向存储在堆中的一个对象。复制操作结束后,两个变量实际上引用同一个对象,因此改变其中一个变量,就会影响另外一个变量。
var person = { name:'Tom' }; function obj(peo){ peo.name = 'Jerry'; return peo; } var result = obj(person); console.log(result.name);//Jerry console.log(person.name);//Jerry
在上面的例子中,把person(person是一个指向{name:‘Tom’}这个对象的指针)复制传入obj()中并赋值给了局部变量peo(按值传递),peo和person指向了同一个对象,而在obj()函数中peo指针通过引用修改了对象中的name属性,其实修改了person与peo共同指向的对象的name属性,相对应的外部person引用的name属性也就改变了,所以打印出来的为Jerry。
我们再看一个例子:
var person = { name:'Tom' }; function obj(peo){ peo = { name:'Jerry' }; return peo; } var result = obj(person); console.log(result.name);//Jerry console.log(person.name);//Tom
在上述例子中,与前一个并没有什么不同,我们只是在函数内对peo变量进行了重新赋值,将一个新对象的引用地址赋值给了peo,所以peo指向的是函数内部创建的新对象,和全部变量person指向老的对象是不一样的。
注:
引用传递:指从一个变量向另一个变量复制引用类的值时,会将储存在变量对象中的值复制一份放到为新变量分配的空间中,这个值是一个指向储存在堆中的对象的指针。复制结束后,两个变量实际上引用同一个对象。