提示

本文主要介绍 JavaScript 的函数使用。@ermo

# 函数

# 什么是函数

来看一段代码

var n = 2;
var sqaure = n * n;
console.log(square);

上面的例子很简单,就是输出2的平方。在实际开发过程中,唯一不变的就是需求在一直改变,这时候如果要求8的平方,我们就得改代码了。

var n = 8;
var square = n * n;
console.log(square);

为了不书写重复的代码,在 js 中将可以复用的代码抽象出来放到一个盒子中,并起个名字,这个盒子就可以理解为函数。

function square(n) {
    console.log(n + "的平方是:" + (n * n));
}

square(16);
square(8);
square(25);

输出

16的平方是:256
8的平方是:64
25的平方是:625

上例中函数主要分为两个部分:

  • function 开头的为函数的定义部分
  • square() 为函数的调用部分

# 函数定义和调用

函数分为2种:没有返回值的函数和有返回值的函数。

# 无返回值的函数

没有返回值的函数也很好理解,就是一个函数执行完内部代码后不会返回数据。语法如下:

function 函数名称(参数1, 参数2, ..., 参数n) {
    // 执行代码
}

function 为定义函数的关键字。函数名称就是给当前函数取一个名字。

括号中的参数可以为1个,也可以为多个,取决于实际开发需要。

函数定义时括号中的参数称为形参,就像一个占位符,因为这个位置的值还不确定,需要调用的过程中才能知道这个变量真正的值是什么。

大括号中的代码块就是调用函数时要执行的代码。

function sum(a, b, c) {
    var sum = a + b + c;
    console.log(sum);
}

sum(1, 2, 3);

输出

6

上例中定义了一个名称为 sum 的函数,同时定义了三个形参变量 a, b, c

函数 sum 的逻辑也很简单,就是将3个参数求和并打印到控制台上。

sum(1, 2, 3); 就是函数的调用,函数定义后是不会自动执行的,只有在代码某处调用该函数,这是被调用的函数才会执行。函数调用的语法如下:

函数名称(实参1, 实参2, ..., 实参n);

函数调用过程中的参数称为实参,可以不传,也可以传多个,具体要看函数定义了多少个形参。

# 有返回值的函数

有时候我们需要一个函数加工一些数据,然后再将这些数据获取后传递到下游使用,这时候就需要用到有返回值的函数。语法如下:

function 函数名称(参数1, 参数2, ..., 参数n) {
    // 执行代码逻辑
    return 返回值;
}

与无返回值的函数相比,有返回值的函数只比前者多了一行代码,就是在函数内部添加关键字 return 然后再加上具体的返回值。

function sum(a, b, c) {
    var sum = a + b + c;
    return sum;
}

var sumNumber = sum(1, 2, 3);
console.log(sumNumber);

输出

6

将上面的求和代码加工一下,就可以变成有返回值的函数。

此时 sum 函数的作用就是计算3个数的和并返回。

# 作用域

现实生活中,我们拿着现金可以去充公交卡坐公交,也可以去充饭卡去买饭。但是却不能拿着饭卡去坐公交,用公交卡拿着去买饭也是不可以的。

这就是作用域,如果把现金、饭卡和公交卡理解为变量,那么现金就是全局作用域内的变量,简称为全局变量,在 js 中打开一个页面就是一个全局作用域;公交卡和饭卡就私有作用域的变量,简称为私有变量,私有变量只在函数中才有。

var n = 1;
function fn1() {
    var n1 = 1;
}
function fn2() {
    var n2 = 1;
}

上述例子中变量 n 为全局变量,变量 n1n2 分别在2个不同的私有作用域中,都是私有变量。

关于变量的访问优先级,先确定当前作用域有没有访问变量,如果没有就向上级作用域查找,以此类推,直到最后找到全局作用域。

var name = "global";

function fn() {
    var name = "fn";

    function fn1() {
        var name = "fn1";
        console.log(name);
    }

    fn1();
}

fn();

上例中最终输出的是 fn1。变量 name 在函数 fn1 的私有域中存在,所以不用向上寻找,直接输出即可。