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閱讀 230,527評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,687評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,640評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,957評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,682評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,011評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,009評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,183評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,714評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,435評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,665評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,148評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,838評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,251評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,588評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,379評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,627評論 2 380

推薦閱讀更多精彩內容