一、函数基础

利用函数来实现低耦合高内聚

  1. // 函数基础
  2. function test(a, b, c){
  3. // 执行语句
  4. }
  5. // 一下代码耦合度比较高
  6. if(3 > 0){
  7. for(var i = 0; i < 10; i++){
  8. console.log(i);
  9. }
  10. }
  11. if(2 > 0){
  12. for(var i = 0; i < 10; i++){
  13. console.log(i);
  14. }
  15. }
  16. if(1 > 0){
  17. for(var i = 0; i < 10; i++){
  18. console.log(i);
  19. }
  20. }
  21. // 耦合
  22. // 低耦合,高内聚 -> 单一模块责任制
  23. // 可以利用函数来节耦合
  24. function test(){
  25. for(var i = 0; i < 10; i++){
  26. console.log(i);
  27. }
  28. }
  29. if(3 > 0){
  30. test();
  31. }
  32. if(2 > 0){
  33. test();
  34. }
  35. if(1 > 0){
  36. test();
  37. }

1.1、函数最基本的写法,函数声明

  • 函数只有调用了,才会执行,函数可以执行多次

    1. // 函数最基本的写法,函数声明
    2. function 函数名(参数「可选」){
    3. // 执行语句
    4. }
    5. // 函数只有调用了,才会被执行
    6. test();
    7. function test(){
    8. console.log('我要开始执行函数了哦');
    9. }
    10. test();

    1.2、函数的命名规则

  • 使用数字、字母、下划线、$组成,但是不能以数字开头

  • 严格区分大小写
  • 不能使用关键字和保留字
  • ECMA建议使用小驼峰命名

    二、函数的种类

    2.1、声明式函数

    1. // 声明式函数
    2. function test(){
    3. var a = 1,
    4. b = 2;
    5. console.log(a ,b);
    6. }
    7. test();

    2.2、表达式 函数字面量

    1. // 匿名函数表达式 函数字面量
    2. var test = function func(){ //func这个函数名只能在函数内部使用,一般用于递归
    3. var a = 1,
    4. b = 2;
    5. console.log(a, b);
    6. }
    7. test();
    8. func(); //Uncaught ReferenceError: func is not defined

    2.3、匿名函数表达式

    1. // 匿名函数表达式 字面量
    2. var func = function(){
    3. console.log('我是匿名函数表达式');
    4. }
    5. func();

    2.4、函数的组成

  • 函数名

  • 参数「可选」
  • 必须要有return,如果不写,JS引擎在解析代码的时候会自动加上 ```javascript // 函数的组成:函数名、参数「可选」、return返回,不写JS引擎在解析代码的时候会自动加上 function 函数名(形参「可选」){
    1. // 执行语句
    2. return;
    }
  1. var aa = Number(window.prompt('a'));
  2. var bb = Number(window.prompt('b'));
  3. // 占位,形式上占位,形式参数, 形参
  4. function func(a, b){
  5. var sum = a + b;
  6. console.log(sum);
  7. return;
  8. }
  9. // 实际传递的参数,实参
  10. func(aa, bb);
  1. <a name="X79Vf"></a>
  2. # 三、函数形参和实参的映射关系
  3. <a name="DM4ED"></a>
  4. ## 3.1、函数的形参数量和实参数量可以不相等
  5. - 函数的形参数量和实参数量可以不相等
  6. - 函数执行时,如果不传递实参;那么函数的形参默认值是undefined
  7. ```javascript
  8. // 函数形参和实参的映射关系
  9. // 函数的形参数量和实参数量可以不相等
  10. // 函数的形参默认值是undefined
  11. function func1(a, b, c){
  12. console.log(a, b, c);
  13. }
  14. func1(1, 2);
  15. function func2(a, b){
  16. console.log(a, b);
  17. }
  18. func2(1, 2, 3);

3.2、实参集合arguments

  • 在实参里面传递了值,可以在函数内部修改这个值
  • 在实参里没有传递这个值,在函数内部给这个形参赋值是没有用的
  • 函数的形参和实参存在映射关系,但绝对不是同一个东西

    1. // 函数的实参集合arguments
    2. // 在实参里面传递了值,可以在函数内部修改这个值
    3. // 在实参里没有传递这个值,在函数内部给这个形参赋值是没有用的
    4. // 函数的形参和实参存在映射关系,但绝对不是同一个东西
    5. function func1(a, b){
    6. console.log(arguments);
    7. }
    8. func1(1, 2, 3, 4, 5);

    循环打印实参集合

    1. // 循环打印实参集合
    2. function func2(){
    3. for(var i = 0; i < arguments.length; i++){
    4. console.log(arguments[i]);
    5. }
    6. }
    7. func2(1, 2, 3, 'a');

    利用实参实现任意数求和

    1. // 利用实参集合求任意数的和
    2. var a = Number(window.prompt('请输入a的值'));
    3. var b = Number(window.prompt('请输入b的值'));
    4. var c = Number(window.prompt('请输入c的值'));
    5. function sum(){
    6. var total = 0;
    7. for(var i = 0; i < arguments.length; i++){
    8. total += arguments[i];
    9. }
    10. console.log(total);
    11. }
    12. sum(a, b, c);

    3.3、函数形参和实参的长度

    1. // 函数形参和实参的长度
    2. function func(a, b){
    3. // 打印函数形参的长度
    4. console.log(func.length);
    5. // 打印函数实参的长度
    6. console.log(arguments.length);
    7. console.log(arguments[2]);
    8. }
    9. func(1, 2, 3, 4, 5);

    3.4、关于函数内部是否可以修改实参值的情况

  • 如果在函数执行时,传递 了实参,那么在函数内部是可以修改这个实参的

  • 如果在函数执行时,没有传递实参,那么在函数内部是无法修改该值的

    1. // 函数内部是否可以修改实参值的问题
    2. // 函数在执行时传递了实参,那么在函数内部可以修改该值
    3. function func1(a, b){
    4. a = 3;
    5. console.log(arguments[0]); // 3
    6. }
    7. func1(1, 2);
    8. // 函数执行时没有传递实参,那么在函数内部无法修改该值
    9. function func2(a, b){
    10. b = 4;
    11. console.log(arguments[1]); // undefined
    12. }
    13. func2(1);

    四、函数中的return

  • 每一个函数都有return,如果不写,那么JS引擎在解析代码的时候会在函数最末尾加上return

  • return有两个作用,一是终止函数的作用,return下面的代码将不会再执行;而是返回一个值,这个值可以是任意类型的,与此同时它仍旧具备终止函数运行的作用

    1. // 函数中的return
    2. // 每一个函数都有return,如果不写,那么JS引擎在解析代码的时候会在函数最末尾加上return
    3. // return有两个作用,一是终止函数的作用,return下面的代码将不会再执行;而是返回一个值,这个值可以是任意类型的,与此同时它仍旧具备终止函数运行的作用
    4. function func(){
    5. console.log('我要开始执行函数了');
    6. return; // return下面的代码就不会被执行
    7. console.log('我已经执行完函数了');
    8. }

    || 遇到真就返回,遇到假就往后走,走到最后不管真或者是假都返回该值
    && 遇到假就返回,遇到真就往后走,走到最后不管真或者是假都返回该值

    1. function func1(name){
    2. if(!name){
    3. return;
    4. }
    5. console.log(name);
    6. }
    7. func1();
    8. func1('liangyu');
    9. // 代码优化
    10. // || 遇到真就返回,遇到假就往后走,走到最后不管真或者是假都返回该值
    11. // && 遇到假就返回,遇到真就往后走,走到最后不管真或者是假都返回该值
    12. function func2(name){
    13. return name || '您没有填写姓名';
    14. }
    15. console.log( func2());
    16. console.log(func2('mac'));

    return返回值:可以返回任意类型的值,return后面的代码将不再执行,也有终止函数的作用

    1. // 返回值return
    2. function func1(name){
    3. if(!name){
    4. return '您没有填写姓名';
    5. }
    6. return name;
    7. }
    8. console.log(func1());
    9. console.log(func1('mac'));
    10. // 代码优化
    11. function func2(name){
    12. return name || '您没有填写姓名';
    13. }
    14. console.log(func2());
    15. console.log(func2('liangyu'));

    五、初始函数作用域 [[scope]]

    • 函数体内部可以访问外部的变量,外部打印执行是无法访问到函数内部的变量的
    • 越里面的函数越能访问到外面的变量,越是外面的访问函数内部的变量是访问不到的
    • 越里面的函数是可以修改外面的变量的
    • 暂且理解:每一个函数都是一个独立的作用域
  1. // 初始函数作用域 [[scope]]
  2. // 函数体内部可以访问外部的变量,外部打印执行是访问不到函数体内部的变量的
  3. a = 1;
  4. function func(){
  5. var b = 2;
  6. console.log(a);
  7. }
  8. func(); // 1
  9. console.log(typeof(b));
  10. console.log(b);

越里面的函数越能访问到外部的变量,越外面的访问函数内部的变量是访问不到的

  1. // 越里面的函数越能访问到外部的变量,越外面的访问函数内部的变量是访问不到的
  2. // 全局变量
  3. a = 1;
  4. function test1(){
  5. // 局部变量
  6. var b = 2;
  7. console.log(a, b);
  8. function test2(){
  9. // 局部变量
  10. var c = 3;
  11. }
  12. test2();
  13. console.log(c);
  14. }
  15. test1();

越是里面的函数越能修改函数体外的变量

  1. // 越是里面的函数越能修改函数体外的变量
  2. a = 1;
  3. function test1(){
  4. var b = 2;
  5. function test2(){
  6. var c = 3;
  7. a = 3;
  8. }
  9. test2();
  10. }
  11. test1();
  12. console.log(a);

暂且理解:每一个函数都是一个独立的作用域

  1. // 暂且理解:每一个函数都是一个独立的作用域
  2. function test1(){
  3. var a = 1;
  4. console.log(b);
  5. }
  6. function test2(){
  7. var b = 2;
  8. console.log(a);
  9. }
  10. test1();
  11. test2();

六、函数式编程

函数式编程:一个固定的功能或者是程序段被封装的过程,实现一个固定的功能或者是程序;这个封装体需要一个入口和出口

  • 入口就是形参
  • 出口就是返回 return

    1. // 函数式编程:一个固定的功能或者是程序段被封装的过程,实现一个固定的功能或者是程序;这个封装体需要一个入口和出口
    2. function func(str){
    3. return str;
    4. }
    5. console.log( func('liangyu'));

    七、作业

  1. 定义一个函数,从window.prompt接收饮料名字,返回对应的价格
  2. 定义一个函数,从window.prompt接收第一个数,接收一个运算符「+ - * 、 %」,再接收一个数,利用这个函数做运算并返回结果
  3. 定义一个函数,从window.prompt接收一个n,算出n的阶乘;不能用for循环
  4. 定义一个函数,从window.prompt接收一个n,算出斐波拉契数列的第n为;不能用for循环