美文网首页
JavaScript函数(一)声明、参数

JavaScript函数(一)声明、参数

作者: Fakecoder_Sunis | 来源:发表于2019-02-15 21:43 被阅读0次

    函数的声明

    JavaScript 有三种声明函数的方法。

    (1)function 命令

    function命令声明的代码区块,就是一个函数。function命令后面是函数名,函数名后面是一对圆括号,里面是传入函数的参数。函数体放在大括号里面。

    function print(s) {
      console.log(s);
    }
    

    上面的代码命名了一个print函数,以后使用print()这种形式,就可以调用相应的代码。这叫做函数的声明(Function Declaration)。

    (2)函数表达式

    除了用function命令声明函数,还可以采用变量赋值的写法。

    var print = function(s) {
      console.log(s);
    };
    

    这种写法将一个匿名函数赋值给变量。这时,这个匿名函数又称函数表达式(Function Expression),因为赋值语句的等号右侧只能放表达式。

    采用函数表达式声明函数时,function命令后面不带有函数名。如果加上函数名,该函数名只在函数体内部有效,在函数体外部无效。

    var print = function x(){
      console.log(typeof x);
    };
    
    x
    // ReferenceError: x is not defined
    
    print()
    // function
    

    上面代码在函数表达式中,加入了函数名x这个x只在函数体内部可用,指代函数表达式本身,其他地方都不可用。这种写法的用处有两个,一是可以在函数体内部调用自身,二是方便除错(除错工具显示函数调用栈时,将显示函数名,而不再显示这里是一个匿名函数)。因此,下面的形式声明函数也非常常见。

    var f = function f() {};
    

    需要注意的是,函数的表达式需要在语句的结尾加上分号,表示语句结束。而函数的声明在结尾的大括号后面不用加分号。总的来说,这两种声明函数的方式,差别很细微,可以近似认为是等价的。

    (3)Function 构造函数

    第三种声明函数的方式是Function构造函数。

    var add = new Function(
      'x',
      'y',
      'return x + y'
    );
    
    // 等同于
    function add(x, y) {
      return x + y;
    }
    

    上面代码中,Function构造函数接受三个参数,除了最后一个参数是add函数的“函数体”,其他参数都是add函数的参数。

    你可以传递任意数量的参数给Function构造函数,只有最后一个参数会被当做函数体,如果只有一个参数,该参数就是函数体。

    var foo = new Function(
      'return "hello world";'
    );
    
    // 等同于
    function foo() {
      return 'hello world';
    }
    

    Function构造函数可以不使用new命令,返回结果完全一样。

    总的来说,这种声明函数的方式非常不直观,几乎无人使用。

    参数

    函数运行的时候,有时需要提供外部数据,不同的外部数据会得到不同的结果,这种外部数据就叫参数。

    function square(x) {
      return x * x;
    }
    
    square(2) // 4
    square(3) // 9
    

    上式的x就是square函数的参数。每次运行的时候,需要提供这个值,否则得不到结果。

    参数的省略

    函数参数不是必需的,JavaScript 允许省略参数。

    function f(a, b) {
      return a;
    }
    
    f(1, 2, 3) // 1
    f(1) // 1
    f() // undefined
    
    f.length // 2
    

    上面代码的函数f定义了两个参数,但是运行时无论提供多少个参数(或者不提供参数),JavaScript 都不会报错。省略的参数的值就变为undefined。需要注意的是,函数的length属性与实际传入的参数个数无关,只反映函数预期传入的参数个数。

    但是,没有办法只省略靠前的参数,而保留靠后的参数。如果一定要省略靠前的参数,只有显式传入undefined

    function f(a, b) {
      return a;
    }
    
    f( , 1) // SyntaxError: Unexpected token ,(…)
    f(undefined, 1) // undefined
    

    上面代码中,如果省略第一个参数,就会报错。

    传递方式

    函数参数如果是原始类型的值(数值、字符串、布尔值),传递方式是传值传递(passes by value)。这意味着,在函数体内修改参数值,不会影响到函数外部。

    var p = 2;
    
    function f(p) {
      p = 3;
    }
    f(p);
    
    p // 2
    

    上面代码中,变量p是一个原始类型的值,传入函数f的方式是传值传递。因此,在函数内部,p的值是原始值的拷贝,无论怎么修改,都不会影响到原始值。

    但是,如果函数参数是复合类型的值(数组、对象、其他函数),传递方式是传址传递(pass by reference)。也就是说,传入函数的原始值的地址,因此在函数内部修改参数,将会影响到原始值。

    var obj = { p: 1 };
    
    function f(o) {
      o.p = 2;
    }
    f(obj);
    
    obj.p // 2
    

    上面代码中,传入函数f的是参数对象obj的地址。因此,在函数内部修改obj的属性p,会影响到原始值。

    注意,如果函数内部修改的,不是参数对象的某个属性,而是替换掉整个参数,这时不会影响到原始值。

    var obj = [1, 2, 3];
    
    function f(o) {
      o = [2, 3, 4];
    }
    f(obj);
    
    obj // [1, 2, 3]
    

    上面代码中,在函数f内部,参数对象obj被整个替换成另一个值。这时不会影响到原始值。这是因为,形式参数(o)的值实际是参数obj的地址,重新对o赋值导致o指向另一个地址,保存在原地址上的值当然不受影响

    相关文章

      网友评论

          本文标题:JavaScript函数(一)声明、参数

          本文链接:https://www.haomeiwen.com/subject/uqueeqtx.html