Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

函数类型(参数) #21

Open
adodo0829 opened this issue Mar 20, 2020 · 0 comments
Open

函数类型(参数) #21

adodo0829 opened this issue Mar 20, 2020 · 0 comments

Comments

@adodo0829
Copy link
Owner

函数类型(参数: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, 被修改了!

故调用函数传参时,函数接受对象实参引用的副本(虽是副本,引用的对象是相同的)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant