函数类型(参数)
Opened this issue · 0 comments
adodo0829 commented
函数类型(参数:arguments对象)
js 函数不限定传递进来多少个参数, 以及参数的数据类型,甚至可以不传参数
arguments对象
函数参数的一些情况, 实参&形参
形参类型不指定,随意传,所以要在函数内部检测
函数调用不对实参进行类型检查, 个数也不定
function add(x) {
return x+1;
}
# 不同的传递和调用结果也不同, 违背了单一原则
console.log(add(1)); // 2
console.log(add('1')); // '11'
console.log(add()); // NaN
console.log(add(1,2)); // 2
- 形参同名情况
在非严格模式下,函数中可以出现同名形参,且只能访问最后出现的该名称的形参
function add(x,x,x){
return x ;
}
console.log(add(1,2,3)); // 3
而在严格模式下,出现同名形参会抛出语法错误
- 参数个数
1.实参 < 形参: 剩下的形参都将设置为undefined值
function add(x,y){
console.log(x,y);
}
add(1); // 1 undefined
2.实参 > 形参: 剩下的实参没有办法直接获得,通过arguments对象
函数参数在内部用一个数组表示。
函数接收到的始终都是这个数组,而不关心数组中包含哪些参数。
在函数体内可以通过arguments对象来访问这个参数数组,
从而获取传递给函数的每一个参数。
arguments对象并不是Array的实例,它是一个类数组对象
function add(x){
console.log(arguments[0],arguments[1],arguments[2]) // 1 2 3
console.log(arguments.length) // 3
return x+1;
}
add(1,2,3); // 2
3. 实参 = 形参: 参数同步,arguments对象的值和对应形参的值保持同步
function test(num1,num2){
// 形参与 arguments的命名空间是独立的, 但值是同步的
// 严格模式下都是独立的
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){
console.log(num1,arguments[0]);// undefined,undefined
num1 = 10;
arguments[0] = 5;
console.log(num1,arguments[0]);// 10, 5
}
test();
- 对象参数
当行参定义的太多时, 往往很麻烦(顺序不能乱), 可以传一个对象进来
function addAverage(numObj) {
return (numObj.x + numObj.y) / numObj.keys().length
}
arguments内部属性
callee
arguments对象有一个名为callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数, 严格模式下,访问这个属性会抛出TypeError错误;
一般用不到
// 递归时使用
function factorial(num){
if(num <=1){
return 1;
}else{
return num* arguments.callee(num-1);
}
}
console.log(factorial(5)); //120
caller
- 函数的 caller属性
函数的caller属性保存着调用当前函数的函数的引用
,如果是在全局作用域中调用当前函数,它的值是null
function outer(){
inner();
}
function inner(){
console.log(inner.caller);
}
outer(); // ƒ outer(){ inner();}
inner(); // null
- arguments对象的caller
该属性始终是undefined,定义这个属性是为了分清arguments.caller和函数的caller属性
通过参数实现函数重载
同一个函数根据传入的参数不同具有不同的功能.
可以通过检查传入函数中参数的类型和数量并作出不同的反应,来模仿方法的重载
function doAdd(){
if(arguments.length == 1){
alert(arguments[0] + 10);
}else if(arguments.length == 2){
alert(arguments[0] + arguments[1]);
}
}
doAdd(10); // 20
doAdd(30,20);// 50
参数传递(值传递,地址传递)
- 参数为基础类型
# 值传递
var a = 1
function fn(o) {
o = 3;
console.log(o) // 3
}
fn(a);
console.log(a) // 1
- 参数为引用类型(拷贝地址)
# 对函数形参的赋值,不会影响实参的值
var obj = {x : 1};
function fn(o) {
o = 100; // 此时相当于一个局部变量
console.log(o) // 100
}
fn(obj);
console.log(obj.x); // 仍然是1, obj并未被修改为100.
# 修改形参对象的属性值,也会影响到实参的属性值
# 会将外部对象内存中的地址复制给一个局部变量
var obj = {x : 1};
function fn(o) {
o.x = 3;
}
fn(obj);
console.log(obj.x); // 3, 被修改了!
故调用函数传参时,函数接受对象实参引用的副本(虽是副本,引用的对象是相同的)