函数是一段可以重复使用的代码段
把一段相对独立的具有特定功能的代码块封装起来,形成一个独立实体,起个名字(函数名),在后续开发中可以反复调用。
函数的作用就是封装一段代码,将来可以重复使用。

定义函数

  1. function 函数名(){
  2. 函数体 - 需要重复时候用的代码
  3. }
  4. function tellStory() {
  5. console.log('从前有座山,山上有座庙');
  6. console.log('庙里有个老和尚和一个小和尚');
  7. console.log('老和尚正在给小和尚讲故事');
  8. console.log('讲的什么呢?');
  9. }
  10. 注意点: 函数里面的代码是不会执行的,需要调用才会执行
  11. 函数的调用:
  12. 然而我们写出上面函数的代码之后,在浏览器中打开页面,
  13. 却没有任务内容被输出。这是因为函数在定义的时候,
  14. 里面的代码是不会执行的,只有调用了函数,函数中的代码才会执行。
  15. tellStory()//函数名();
  16. 每调用一次,就会执行一次,做了代码的重复使用。
  17. 一定要记住,函数定义时是不会执行的,只有调用时才会执行。
  18. 可以使用代码调试工具进行代码执行过程观察。

函数的参数

重复使用函数的过程会有变化的值,就可以用参数解决
语法:
function 函数名(参数){
函数体
}

  1. function fn(n){
  2. console.log(n)//此时n的内容是 函数体
  3. }
  4. fn(函数体)

就是说参数就好像函数里面的一个变量一样,可以存储一个随时变量的数据
当我们调用函数的时候,再给一个真实的值
函数的参数可以一个,也可以是多个,只要在重复的过程中,有多个会产生变化的数据,都可以使用参数的方式解决
在定义函数时写的占位用的参数,我们称为形参,在调用函数,实际参与函数执行的参数,我们称为实参

函数的返回值

函数执行完毕之后会有一个执行结果,该结果就叫 —— 返回值
如果你希望函数执行完毕之后,有一个你想要的数据,就可以使用返回值来实现
函数默认情况下,得到的结果是 —— undefined
想要修改可以修改,使用return修改
函数体没有写return 在函数外是访问不了的
函数体写了return 就会得到return 后面需要返回的内容
return 跳出函数, 下面的代码不会继续执行

补充函数

函数表达式

  1. var 函数名 = function(参数){
  2. 函数体
  3. }
  4. var getSum = function(a,b){
  5. return a + b;
  6. }

匿名函数

没有名字的函数

  1. function (参数){ 函数体 }

自调用函数

  1. (function({
  2. // 写一些为了避免变量污染的代码
  3. }))();

全局和局部作用域

函数和变量的有效范围就是作用域

作用域

  1. var a = 10;
  2. function f1(){
  3. console.log(a);
  4. }
  5. f1();// 变量a在函数外定义,可以在函数内使用
  6. function f2(){
  7. var b = 20;
  8. }
  9. console.log(b); // 变量b在函数内定义,在函数外无法访问,报错: b is not defined

这是因为js中存在作用域的概念。
作用域:
作用域就是指定一个变量或者一个函数的作用范围。
能在页面的任何位置都可以访问,称为 全局作用域
只能在函数内访问,称为为 局部作用域
在全局作用域下声明的变量,称为 全局变量
在局部作用域下声明的变量,称为 局部变量
上述代码中,a是全局变量,b是局部变量

全局

script标签或者是一个js文件内部直接定义的
在全局下定义的变量在任何位置都可以使用,称为全局变量

局部

函数内部就是局部作用域

  1. function fn(){
  2. var b = 10; // b就是局部变量
  3. }

局部作用域里面的数据,外面是访问不了的。
作用域的作用就是为了把数据进行保护,不让外部的数据对我们的数据进行污染

作用域链

在JavaScript里面,函数内部是可以包含另一个函数的

  1. function a(){
  2. function b(){
  3. }
  4. }
  5. 此时函数b就被函数a包含越来了,这样就形成了两层作用域。

预解析

因为在js中,代码执行之前,会先进行一次预解析
预解析就是在执行代码之前,把代码中的变量声明和函数声明,提升到当前作用域的最顶端,而变量的赋值和函数的调用还在原来的位置。

  1. f1();
  2. console.log(c);
  3. console.log(b);
  4. console.log(a);
  5. function f1() {
  6. var a = b = c = 9;
  7. console.log(a);
  8. console.log(b);
  9. console.log(c);
  10. }
  11. //以上代码预解析
  12. function f1() {
  13. var a
  14. a = 9
  15. b = 9 //没有声明的值是全局的
  16. c = 9;//没有声明的值是全局的
  17. console.log(a); 9
  18. console.log(b);9
  19. console.log(c);9
  20. }
  21. f1();
  22. console.log(c); 9
  23. console.log(b); 9
  24. console.log(a); //报错获取不了局部的

arguments

我们求三个数的和可以调用求两个数的和的函数,那么要求四个数的和也调用求三个数的和的函数,这样如果要求n个数的和,就要写n-1个函数了,这样是很麻烦的
在js中,函数的实参和形参的个数是允许不同的

  1. function fn(a,b){
  2. return a + b;
  3. }
  4. fn(1,2,3,4);// 正常执行,不会报错

但是我们如果得到在实参里多出的3和4呢?js里面提供了一个在函数中专用的,获取所有实参的对象:arguments

  1. function fn(){
  2. console.log(arguments);
  3. }
  4. fn(1); // 输出 [1]
  5. fn(1,2) // 输出 [1,2]
  6. fn(1,2,3,4,5) // 输出 [1,2,3,4,5]

arguments 这个东西看起来像数组,但是其实不是一个数组,我们管它叫 伪数组。它具有数组的长度和顺序等特征。
arguments这个东西就解决了我们要求n个数字的和的问题

  1. function getSum(){
  2. var sum = 0;
  3. for(var i = 0; i < arguments.length ; i++){
  4. sum += arguments[i];
  5. }
  6. return sum;
  7. }
  8. getSum(1,2,3);// 输出 6
  9. getSum(1,2,3,4,5); // 输出15