Js基础-函数

函数是实现功能的载体, 它应该是一个最小功能的封装, 比如我们要计算两个数之和,再比如我们要实现计算正方形的体积等等。

函数定义和调用

函数定义

我们使用 function 关键字定义函数

// demo 为函数名, 自己命名但必须符合JS标识符命名规则
// () 小括号中可以带参数, 这种参数还有个称呼 叫做 形式参数 简称形参 。 形参可以省略,但小括号不能省
// {} 大括号内部的函数就是逻辑运算部分, 如果我们要计算 传入的 a、b 的和,就可以在这里写
function demo(a, b){
   // 函数的主题内容
}

函数调用

我们希望在哪里执行定义的函数, 就在哪里进行调用。

// 函数调用,写清楚函数名称,已经调用的参数
demo(2, 3);

从函数定义中,我们可以看出函数总共由三部分构成, 输入、输出和计算

输入告诉我们外部的一些变量值,然后通过计算把结果输出

输入

输入传的值,我们也叫形参,即形式参数,意思是我们还不知道具体传什么值,先拿一个变量占上坑。如函数定义中的 a, b 两个参数

当我们具体调用的时候才会确定要传什么值, 这时候的参数叫做实参(实际参数)

// 传入 2, 3 在函数运算的时候会替换掉 形参, 所以我们叫他们实参
demo(2, 3);

形参 和 实参 有时候数量并不相等,不等情况有两种

  1. 形参比实参多

<script>
  function print(a, b , c) {
		console.log("a=", a,",b=",b,",c=",c);
	}

// 形式参数 定义了三个 a, b ,c 但此时之传入了两个, 则 1赋值给 a , 2赋值给b , c 只能为 undefined了
print(1, 2)
</script>

  1. 实参比形参多

<script>
  function print(a, b , c) {
		console.log("a=", a,",b=",b,",c=",c);
	}

// 形式参数 定义了三个 a, b ,c , 但是我们没有形参接受4 这个实际传入的参数,这个参数在这个运算中只能被抛弃
print(1, 2, 3,4)
</script>

实际需求中我们应该能准确的使用函数,使得形参和实参一一对应

但有时候,又有一些场景,我们想在被调用的函数中能够获取到所有传入的实际参数。比如:求传入的所有实参的和。

这种场景,需要 arguments, arguments 能够像数组那样遍历,获得所有实参

<script>
    function plus() {
        var resultPlus = 0;
        for(var i = 0 ; i < arguments.length ; i++) {
            resultPlus += arguments[i];
        }
        return resultPlus;
    }

    var result = plus(1,2,3,4,5)
    console.log(result);

</script>

输出

从函数定义的例子当中,我们并没有看到输出,即函数并没有返回任何结果

这是因为在一个函数中,可以没有输入、也可以没有输出、甚至也可以把函数计算也拿掉(空函数, 当然这种函数没有任何现实意义)

如果我们函数运算完成后需要返回值怎么办?

好办,用 return 关键字, 举个栗子,我们想计算 两个数的和,并返回计算结果, 代码如下

<script>
        function plus(a, b){
            return a + b;
        }
</script>

如果代码能执行到return语句就意味着函数运行结束了, 它会把代码的执行权先归还给调用者

匿名函数

以上的例子中,函数都有名字;我们改造下, 就会得到匿名函数,匿名函数就是没有名字的函数

function(a,b) {
	// 函数主体内容
}

如果我们把上面的函数运行在浏览器,肯定会报错, 因为任何函数定义出来都是要调用执行的,上面定义的函数报错就是因为浏览器不知道如何运行引起的

所以这么写是不完整的, 根据需要,我们可以用以下的思路定义匿名函数

将匿名函数赋值给变量

var fun = function(a, b) {
	// 
}

这样,我们的函数居然又拥有了一个“名字”

当然函数的调用的写法不变

fun(a,b);

用小括号包裹

<script>
        (function (a,b ){
            console.log('hello', a,b)
        })
</script>

这种方式只是定义,我们无法在其他地方调用它,同样也无法执行, 这貌似打破了我们上面说的:一个函数定义出来就是要调用执行的说法

所以为了把这句话圆回去,我们必须加点东西,我们再加一个小括号,把它变成立即执行函数;也就是说我们在函数定义的地方调用它,当浏览器解析到此代码的时候立即执行。

<script>
      (function (a,b ){
          console.log('hello', a,b)
      })();
</script>

立即执行函数,既保证了在定义的地方可以调用,也保证的 任何函数都需要调用执行的说法

回调函数

函数还可以作为一个参数值传给其它函数, 其它参数执行到具体代码会自动调用。

我们上一篇

数组

紫薯自书,公众号:优雅编程JS基础-复杂数据类型之数组

提到的排序的例子,就是把一个函数当作形参传入到了另外函数中

var sortArray = array.sort(function(a, b){
      return b-a;
});

把函数当成一个返回值

函数还可以当成返回值返回给调用方

<script>
      function plus(a, b){

					
          return function() {
              return a + b;
          } 
      }

      var plusResult = plus(1,2);

      var plusResultFunResult = plusResult();
      console.log(plusResult);
      console.log(plusResultFunResult);
</script>

上面这个例子, plus 函数返回了一个函数给调用方

plusResult 指向的是一个函数

plusResultFunResult 指向的才是最终的运算结果

如果我们只想得到结果,省略啰嗦的函数赋值给引用变量的过程,我们也可以像下面一样这么做

<script>
        function plus(a, b){
            return function() {
                return a + b;
            } 
        }
        var plusResultFunResult = plus(1,2)();
        console.log(plusResultFunResult);
    </script>

函数的执行顺序

一个函数执行的顺序,是从调用开始, 逐行开始执行,直到遇见return或者函数最后一行结束。最终函数执行结束后会把调用权交还给函数。