JavaScript函数0710

JavaScript函数

1.函数格式

  • function 函数名称(形参列表){

    ​ return x;

    }

  • 形参需要和C语言区别,js里边只要==写个形参名字就行==

2.函数的注意点

  • 一个函数可以有形参也可以没有形参(零个或多个)

  • 一个函数可以有返回值也可以没有返回值,没有返回值默认是undefined

  • JavaScript中的函数和数组一样, 都是引用数据类型(对象类型)

    • 既然是一种数据类型, 所以也可以保存到一个变量中,将来可以==通过变量名称找到函数并执行函数==

      • let say = function () {
             console.log("hello world");
        }
        say();
        
  • 调用函数时实参的个数和形参的个数可以不相同 ==我只能说一giao我里giao==

    • function getSum(a, b) {
           console.log(a, b);
           return a + b;
      }
      let res = getSum(10); //b就是undefined
      let res = getSum(10, 20, 30); //多余的收不到
      

3.函数arguments

  • 因为console.log();也是通过()来调用的, 所以log也是一个函数,为什么log函数可以接收1个或多个参数,内部的实现原理就用到了arguments

  • arguments的作用:保存所有传递给函数的实参,我们写一个求和函数

    • function getSum() {
      // 注意点: 每个函数中都有一个叫做arguments的东西
      // arguments其实是一个伪数组,可以通过下标索引取值
      // console.log(arguments);
          let sum = 0;
          for (let i = 0; i < arguments.length; i++){
              let num = arguments[i];
              // console.log(num); // 10 20 30
              sum += num; 
          }
           return sum;
      }
      //这样我们就实现了不管有多少参数都能求和
      let res = getSum(10, 20, 30, 40);
       console.log(res);
      
      

4.函数扩展运算符

  • 扩展运算符在函数的形参列表中的作用

    • 将传递给函数的所有实参打包到一个数组中,注意和在等号左边一样, ==也只能写在形参列表的最后==

      • function getSum(...values) {
          //也可以实现不管多少个实参都能相加
          // console.log(values);
           let sum = 0;
           for (let i = 0; i < values.length; i++){
                let num = values[i];
                 sum += num;
              }
            return sum;
        }
        let res = getSum(10, 20, 30, 40);
        console.log(res);
        //只能写在最后面哦
        function getSum(a, ...values)
        

5.函数形参默认值

  • 在ES6之前可以通过逻辑运算符来给形参指定默认值

  • 格式: 条件A || 条件B,如果条件A成立, 那么就返回条件A,如果条件A不成立, 无论条件B是否成立, 都会返回条件B

    • function getSum(a,b){
          a=a||"tanwenchao";
          b=b||"lalala";
          console.log(a,b);
      }
      getSum(); //就算没传也有值
      

从ES6开始, 可以直接在形参后面通过=指定默认值

  • 注意点: ES6开始的默认值还可以从其它的函数中获取

    • //function getSum(a = "tan", b = "xu") {
      //下面试通过函数获取
      function getSum(a = "指趣学院", b = getDefault()) {
               console.log(a, b);
      }
      getSum();
      // getSum(123, "abc");
      function getDefault() {
           return "tan"
      }
      
      

6.函数作为参数和返回值

注意点:在进行参数传递操作时,要想一想带括号和不带括号,比如下面

  • let say = function () {
        console.log("hello world");
    }
    let fn = say;
    fn();
    //我也可以这样写
    let fn = say();
    fn;
    
    
  • 作为返回值

    • 在其它编程语言中函数是不可以嵌套定义的

    • function test() {
          let say = function () {
              console.log("hello world");
           }
           return say;
      }
      let fn = test(); // 相当于let fn = say;
      fn();
      
  • 作为参数

    • let say = function () {
           console.log("hello world");
      }
      function test(fn) { // let fn = say;
           fn();
      }
      test(say);
      

7.匿名函数

匿名函数就是没有名称的函数

  • 作为其他函数的返回值

    • function test() {
           return function () {
              console.log("hello lnj");
            };
      }
      let fn = test(); // let fn = say;
      fn();
      
  • 作为一个立即执行的函数

    • 注意点: 如果想让匿名函数立即执行, 那么必须使用()将函数的定义包裹起来才可以

    • (function () {
           console.log("hello it666");
      })();
      
  • 作为其他函数的参数

    • function test(fn) { // let fn = say;
           fn();
      }
      test(function () {
            console.log("hello world");
      });
      

8.箭头函数

箭头函数是ES6中新增的一种定义函数的格式,目的就是为了简化定义函数的代码,相比之前有什么区别呢.如下

  • let 函数名称 = (形参列表) =>{}

  • let say = (name) => {
        console.log("hello"+name);
    }
    say();
    //上面看起来并不简化
    //在箭头函数中如果只有一个形参, 那么()可以省略
    let say = name => {
        console.log("hello"+name);
    }
    //在箭头函数中如果{}中只有一句代码, 那么{}也可以省略
    let say = name => console.log("hello"+name);
    say("谭文超");
    

9.递归函数

和以前学的一样

10.函数中变量作用域

我们知道,js中有两种定义变量的方法,var 和 let ,区别之前已经学过,他们在变量作用域中也有区别

  • 首先了解一下块级作用域和局部作用域
    • 在ES6中只要{}没有和函数结合在一起, 那么应该"块级作用域",例如写在while循环,for循环等
    • 函数后面{}中的的作用域, 我们称之为"局部作用域
  • 在了解一下var和let的作用域的区别
    • 在块级作用域中通过var定义的变量是全局变量,在局部作用域中通过var定义的变量是局部变量==感觉很沙雕的样子==
    • 通过let定义的变量,只要是在{}里就是局部变量,==var和C语言的变量差不多==
    • 无论是在块级作用域还是在局部作用域, 省略变量前面的let或者var就会变成一个全局变量 如 {num = 1;}

11.作用域链基本了解

正是因为有了函数的嵌套,所以才有了作用域链的概念,同时由与ES6之前和之后的语法差异,研究"作用域链"的时候最好将ES6之前和ES6分开研究.

  • ES6之前没有块级作用域, 只有全局作用域和局部作用域

    • 全局作用域我们又称之为0级作用域
    • 定义函数开启的作用域就是1级/2级/3级/...作用域,JavaScript会将这些作用域链接在一起形成一个链条, 这个链条就是作用域链,0 ---> 1 ----> 2 ----> 3 ----> 4
  • 变量在作用域链查找规则

    • 1先在当前找, 找到就使用当前作用域找到的,当前作用域中没有找到, 就去上一级作用域中查找,以此类推直到0级为止, 如果0级作用域还没找到, 就报错

    • var num = 123;
      function demo() {
          // 1级作用域
          var num = 456;
          function test() {
              // 2级作用域
              // var num = 789;
              console.log(num);
           }
           test();
      }
      demo();
      //当前代码会输出456
      

ES6就是多加了一个块级作用域,但是通过let 定义变量不管是新开了一个函数还是一个代码块,都会开启作用域的.

12.函数预解析

  • 什么是预解析:浏览器在执行JS代码的时候会分成两部分操作:预解析以及逐行执行代码,也就是说浏览器不会直接执行代码, 而是加工处理之后再执行, 这个加工处理的过程, 我们就称之为预解析.

  • 预解析规则:将变量声明和函数声明提升到当前作用域最前面,将剩余代码按照书写顺序依次放到后面

  • 三种预解析

    • //下为第一种,会预解析,可以先调用在创建,
      say();
      function say(){
          console.log("谭文超");
      }
      
    • //下为第二种
      say(); 
      // 如果将函数赋值给一个var定义的变量, 那么函数不会被预解析, 只有变量会被预解析
      var say = function() {
            console.log("hello itzb");
      }
      //预解析完是这样的
       /*
      var say; //undefined
      say();// say is not a function
      say = function() {
           console.log("hello itzb");
      }
      */
      
    • //下为第三种
      // ES6定义函数的格式不会预解析
      say(); // say is not defined
      let say = () => {
          console.log("hello itzb");
      }
      

我们来看几个练习

  •       var num = 123;
            fun();
            function fun() {
                console.log(num);
                var num = 666;
            }
          //输出什么东西
            /*
            var num;
            function fun() {
               var num;
               console.log(num); // undefined
               num = 666;
            }
            num = 123;
            fun();
            */
    
    
  •       var a = 666;
            test();
            function test() {
                var b = 777;
                console.log(a);
                console.log(b);
                console.log(c);
                var a = 888;
                let c = 999;
            }
            /*
            var a;
            function test() {
               var b;
               var a;
               b = 777;
                console.log(a); // undefined
                console.log(b); // 777
                console.log(c); // 报错
                a = 888;
                let c = 999;
            }
            a = 666;
            test();
            */
    
  • 下面这个了解一下(面试或笔试)

    •         // 在ES6之前没有块级作用域, 并且没有将这两个函数定义到其它的函数中,
              // 所以这两个函数应该属于全局作用域
              // 注意点:
              // 1.在高级浏览器中, 不会对{}中定义的函数进行提升
              // 2.只有在低级浏览器中, 才会按照正常的方式解析
              if(true){
                  function demo() {
                      console.log("1");
                  }
              }else{
                  function demo() {
                      console.log("2");
                  }
              }
              demo();//高级浏览器输出1
              /*
              低级浏览器如下解析,输出2
              function demo() {
                  console.log("1");
              }
              function demo() {
                  console.log("2");
              }
              if(true){}else{}
              demo();
              */
      
      
    •         // 注意点: 如果变量名称和函数名称同名, 那么函数的优先级高于变量
              // 一定要记住, 在企业开发中千万不要让变量名称和函数名称重名
              console.log(value); // 会输出函数的定义
              var value = 123;
              function value() {
                  console.log("fn value");
              }
              console.log(value); // 会输出123
              /*
              function value() {
                  console.log("fn value");
              }
              console.log(value);
              var value;
              value = 123;
              console.log(value);
              */
      
      
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容