深入理解javascript函数参数
arguments
javascript对参数要求很随意,她才不管你传进来的参数是什么数据类型,甚至可以不传参数。实际上,javascript函数调用甚至不检查传入形参的个数。
1 function add(x){ 2 return x + 1; 3 } 4 console.log(add(1)); //2 5 console.log(add('1')); // 11 6 console.log(add()); // NAN 7 console.log(add(1,2,5)); //2
同名形参
非严格模式下函数可以有同名形参,但之鞥呢访问最后出现的那个。。。
function add(x,x,x,){ return x; } console.log(add(2,5,6)); //6
参数个数
case1:实参比形参少? 那剩下的形参都设置为undefined
1 function add(x,y){ 2 console.log(x,y) 3 } 4 add(1); // 1,undefined
这时候我们可以给y设置一个合理的默认值
1 function add(x,y){ 2 y = y || 10000 3 console.log(x,y); 4 } 5 add(1); //1 10000
case2:形参比实参多? 多了就是废的! 可以通过arguments[i]拿到。
参数再内部是用一个数组表示的,arguments对象并不是Array的实例,它是一个类数组对象。
1 function add(){ 2 console.log(arguments[0],arguments[1],arguments[2]); //1,2,3 3 console.log(arguments[0]+arguments[1]); //3 4 console.log(arguments.length); //4 5 } 6 add(1,2,3,4);
case3:形参和实参一样多? 此时命名参数和对应arguments对象的值相同,但不是相同的命名空间。换句话说,两者值同步,命名空间独立。
callee
arguments对象有个callee属性,是一个指针,指向拥有这个arguments对象的函数,看如下阶乘
function factorial(num){ if(num <= 1){ return 1; }else{ return num * factorial(num - 1); } } factorial(6); //720
1 function factorial(num){ 2 if(num <= 1){ 3 return 1 4 }else{ 5 return num * arguments.callee(num -1); 6 } 7 } 8 factorial(6); //720
caller
函数的caller属性保存着调用当前函数的函数的应用,如果是在全局作用于中调用当前函数,它的值是null
下面这个没撒意义,好玩而已
1 function mother(){ 2 son(); 3 } 4 function son(){ 5 mother(); 6 } 7 mother(); //Uncaught RangeError: Maximum call stack size exceeded 8 //栈溢出。。。
这个才是正道
1 function mother(){ 2 son() 3 } 4 function son(){ 5 console.log(son.caller); 6 } 7 mother(); //function mother(){son()}
arguments对象的caller始终是undefined,这样定义时为了和函数的caller区分开。。
1 function mother(x){ 2 console.log(arguments.caller); 3 } 4 mother(100); //undefined
参数传递
case1:基本类型值
1 function addTen(num){ 2 num += 10; 3 return num; 4 } 5 var count = 20; 6 var result = addTen(count); 7 console.log(count);//20,没有变化 8 console.log(result);//30
case2:引用类型值
在向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化会反应在函数的内部(好特么拗口!!)
1 function setInfo(obj){ 2 obj.name = 'lihong' 3 } 4 var person = new Object(); 5 setInfo(person); 6 console.log(person.name); //lihong
当在函数内部重写引用类型的形参时,这个变量引用的就是一个局部对象了。这个局部对象会在函数执行完毕后立即被销毁
function setInfo(obj){ obj.name = 'lihong'; console.log(person.name); obj = new Object(); obj.name = 'linyao'; console.log(person.name); } var person = new Object();
运行结果:“老公” “老公” 说明了什么? 婆娘不重要!哈哈