整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          JavaScript 回調

          JavaScript 回調

          現代前端開發中,回調函數是一種非常重要的概念。它們允許我們在特定的時刻執行代碼,常用于處理異步操作,例如事件監聽、網絡請求等。在本文中,我將通過幾個例子來深入探討回調函數的使用。

          什么是回調函數?

          回調函數(Callback)是一個作為參數傳遞給另一個函數的函數,這個回調函數將在外部函數的內部被執行。在JavaScript中,由于其事件驅動和異步的特性,回調函數應用非常廣泛。

          示例1:事件監聽回調

          下面是一個簡單的HTML按鈕點擊事件的例子,我們將為按鈕元素添加一個點擊事件監聽器,并傳遞一個回調函數來處理點擊事件。

          <!DOCTYPE html>
          <html lang="zh-CN">
          <head>
              <meta charset="UTF-8">
              <title>回調函數示例:事件監聽</title>
          </head>
          <body>
              <button id="clickMeBtn">點擊我</button>
          
              <script>
                  document.getElementById('clickMeBtn').addEventListener('click', function() {
                      alert('按鈕被點擊了!');
                  });
              </script>
          </body>
          </html>
          

          在這個例子中,我們定義了一個匿名函數作為addEventListener方法的第二個參數。當用戶點擊按鈕時,這個匿名函數就會被調用。

          示例2:異步操作回調

          異步操作,如網絡請求,是回調函數的另一個常見用例。以下是使用XMLHttpRequest對象發起網絡請求的示例。

          <!DOCTYPE html>
          <html lang="zh-CN">
          <head>
              <meta charset="UTF-8">
              <title>回調函數示例:異步操作</title>
          </head>
          <body>
              <script>
                  function requestData(url, callback) {
                      var xhr=new XMLHttpRequest();
                      xhr.open('GET', url, true);
                      xhr.onreadystatechange=function() {
                          if (xhr.readyState===4 && xhr.status===200) {
                              callback(null, xhr.responseText);
                          } else if (xhr.readyState===4) {
                              callback(new Error('請求失敗'));
                          }
                      };
                      xhr.send();
                  }
          
                  requestData('https://api.example.com/data', function(error, data) {
                      if (error) {
                          console.error('發生錯誤:', error);
                      } else {
                          console.log('接收到的數據:', data);
                      }
                  });
              </script>
          </body>
          </html>
          

          在這個例子中,我們定義了一個名為requestData的函數,它接收一個URL和一個回調函數作為參數。requestData函數內部創建一個XMLHttpRequest對象,并在請求完成時調用回調函數,傳遞錯誤對象或響應數據。

          示例3:定時器回調

          JavaScript定時器函數setTimeout和setInterval也使用回調函數。以下是一個使用setTimeout的例子。

          <!DOCTYPE html>
          <html lang="zh-CN">
          <head>
              <meta charset="UTF-8">
              <title>回調函數示例:定時器</title>
          </head>
          <body>
              <script>
                  function delayLog(message, delay) {
                      setTimeout(function() {
                          console.log(message);
                      }, delay);
                  }
          
                  delayLog('3秒后的消息', 3000);
              </script>
          </body>
          </html>
          

          在這個例子中,delayLog函數接收一個消息和一個延遲時間(毫秒)作為參數。它使用setTimeout來延遲執行一個匿名函數,該函數將在指定的延遲后輸出消息。

          結論

          回調函數是JavaScript編程的基石之一,它們提供了一種處理異步操作和事件的強大手段。理解并正確使用回調函數對于任何前端工程師來說都是至關重要的。通過本文的例子,我們可以看到回調函數在實際編程中的多種應用場景,希望這些例子能幫助你更好地理解回調函數的工作原理和使用方法。

          調函數

          定義:回調函數就是一個通過函數指針調用的函數。如果你把函數的指針(地址)作為參數傳遞給另一個函數,當這個指針被用來調用其所指向的函數時,我們就說這是回調函數。

          案例

          案例一:定義一個名為 add 的函數,接收兩個參數,將這個兩個參數相加,作為返回值。當調用這個函數的時候,就可以得到返回值。

          function add(x, y){
              return x + y;
          };
          
          var result=add(10, 20);
          console.log(result);

          運行結果:


          說明:像上面的 add 函數,可以直接得到返回值。


          案例二:定義一個函數 add,也是接收兩個參數,在這個 add 函數中同時定義了一個 setTimeout 函數,想在一秒鐘之后,返回這兩個參數之和。

          演示兩種獲取不到的方法:

          第一種:setTimeout 中返回結果

          function add(x, y){
              console.log(1);
              setTimeout(function(){
                  console.log(2);
                  var result=x + y;
                  return result;
              }, 1000);
              console.log(3);
          };
          
          console.log(add(10, 20));

          運行結果:

          說明:當輸出調用 add 函數的時候,js 代碼從上到下執行,當遇到異步的 setTimeout 函數的時候,不會等待異步函數,繼續往下執行,當執行 console.log(add(10, 20)); 的時候,函數沒有返回值,所以打印出 undefined

          第二種:在外層函數定義一個 result 變量,在 setTimeout 函數里進行賦值。

          function add(x, y){
              var result=0;
              setTimeout(function(){
                  result=x + y;
              }, 1000);
              return result;
          };
          
          console.log(add(20, 20));

          運行結果:

          說明:js 代碼按照順序執行,當執行到 setTimeout 的時候,不會等待,繼續往下執行,所以 result 還是 0。

          正確的獲取方式:通過定義回調函數獲取

          function add(x, y, callback){
              setTimeout(function(){
                  var result=x + y;
                  callback(result);
              }, 1000);
          };
          
          add(30, 20, function(result){
              console.log(result);
          });

          運行結果:

          說明:add 函數中的 callback,只是起的名稱,意思是 回調函數,在輸出調用 add 函數的時候,傳了 x,y 和 一個函數,其實就是將函數的指針(地址)作為參數傳遞給另一個函數,當這個指針被用來調用時,就是去找 function(result){console.log(result)}。所以在調用add 函數的時候,代碼按照正常順序執行,過了 1 秒之后,執行 setTimeout 里的函數,執行到 callback 的時候,會去執行function(result){console.log(result)}


          路漫漫其修遠兮,吾將上下而求索

          譯文:在追尋真理方面,前方的道路還很漫長,但我將百折不撓,不遺余力地去追求和探索。


          如果您有什么好的想法與方法,歡迎在評論區留言,我們一起討論~

          文已經過原作者 dmitripavlutin 授權翻譯!

          回調函數是每個 JS 開發人員都應該知道的概念之一。回調用于數組,計時器函數,promise,事件處理程序等中。

          在本文中,會解釋回調函數的概念。另外,還會幫助智米們區分兩種回調:同步和異步

          1.回調函數

          我們編寫一個問候的函數,首先創建一個函數greet(name),該函數返回歡迎消息:

          function greet(name) {
            return `Hello, ${name}!`;
          }
          
          greet('小智'); // => 'Hello, 小智!'
          

          如果要向一些人問候怎么做?這里,我們可以使用 array.map() 方法:

          const persons = ['小智', '王大冶']
          const messages = persons.map(greet)
          
          messages // ["Hello, 小智!", "Hello, 王大冶!"]
          

          persons.map(greet)接受person數組的每一項,并使用每一項作為調用參數來調用函數greet()greet('小智')greet('王大冶')

          有趣的是persons.map(greet)方法接受greet()函數作為參數。這樣做會使reet()成為回調函數。

          persons.map(greet)是一個接受另一個函數作為參數的函數,因此將其命名為高階函數

          高階函數承擔調用回調函數的全部責任,并為其提供正確的參數。

          在前面的示例中,高階函數persons.map(greet)負責調用greet()回調函數,并將數組的每個項目作為參數:'小智''王大冶'

          我們可以可以自己編寫使用回調的高階函數。例如,這里有一個等價的array.map()方法

          function map(array, callback) {
            const mappedArray = [];
            for (const item of array) { 
              mappedArray.push(
                callback(item)
              );
            }
            return mappedArray;
          }
          
          function greet(name) {
            return `Hello, ${name}!`;
          }
          
          const persons = ['小智', '王大冶']
          
          const messages = map(persons, greet);
          
          messages // ["Hello, 小智!", "Hello, 王大冶!"]
          

          map(array, callback)是一個高階函數,因為它接受回調函數作為參數,然后在它的函數體內部調用回調函數:callback(item)

          2.同步回調

          回調的調用方式有兩種:同步和異步回調。

          同步回調是在使用回調的高階函數執行期間執行的。

          換句話說,同步回調處于阻塞狀態:高階函數要等到回調完成執行后才能完成其執行。

          function map(array, callback) {
            console.log('map() 開始');
            const mappedArray = [];
            for (const item of array) { mappedArray.push(callback(item)) }
            console.log('map() 完成');
            return mappedArray;
          }
          
          function greet(name) {
            console.log('greet() 被調用 ');
            return `Hello, ${name}!`;
          }
          const persons = ['小智'];
          
          map(persons, greet);
          
          // map() 開始
          // greet() 被調用 
          // map() 完成
          

          greet()是一個同步回調函數,因為它與高階函數map()同時執行。

          2.1 同步回調的例子

          很多原生 JavaScript 類型的方法都使用同步回調。

          最常用的是數組方法,例如array.map(callback)array.forEach(callback)array.find(callback)array.filter(callback)array.reduce(callback, init)

          // 數組上的同步回調的示例
          
          const persons = ['小智', '前端小智']
          persons.forEach(
            function callback(name) {
              console.log(name);
            }
          );
          // 小智
          // 前端小智
          
          const nameStartingA = persons.find(
            function callback(name) {
              return name[0].toLowerCase() === '小';
            }
          )
          // nameStartingA // 小智
          
          const countStartingA = persons.reduce(
            function callback(count, name) {
              const startsA = name[0].toLowerCase() === '小';
              return startsA ? count + 1 : count;
            }, 
            0
          );
          
          countStartingA // 1
          

          3.異步回調

          異步回調在執行高階函數之后執行。

          簡而言之,異步回調是非阻塞的:高階函數無需等待回調即可完成其執行,高階函數可確保稍后在特定事件上執行回調。

          在下面的示例中,later()函數的執行延遲為2秒

          console.log('setTimeout() 開始')
          setTimeout(function later() {
            console.log('later() 被調用')
          }, 2000)
          console.log('setTimeout() 完成')
          
          // setTimeout() 開始
          // setTimeout() 完成
          // later() 被調用(2秒后)
          

          3.1 異步回調的示例

          計時器函數的異步回調:

          setTimeout(function later() {
            console.log('2秒過去了!');
          }, 2000);
          
          setInterval(function repeat() {
            console.log('每2秒');
          }, 2000);
          

          DOM 事件監聽器也是異步調用事件處理函數(回調函數的一種子類型)

          const myButton = document.getElementById('myButton');
          
          myButton.addEventListener('click', function handler() {
            console.log('我被點擊啦!');
          })
          // 點擊按鈕時,才會打印'我被點擊啦!'
          

          4. 異步回調函數 vs 異步函數

          放在函數定義之前的特殊關鍵字async創建一個異步函數:

          async function fetchUserNames() {
            const resp = await fetch('https://api.github.com/users?per_page=5');
            const users = await resp.json();
            const names = users.map(({ login }) => login);
            console.log(names);
          }
          

          fetchUserNames()是異步的,因為它的前綴是async。該函數await fetch('https://api.github.com/users?per_page=5')從 GitHub 前5個用戶。然后從響應對象中提取 JSON 數據:await resp.json()

          async函數是 Promise 的語法糖。當遇到表達式await <promise>時(注意,調用fetch()將返回一個 promise),異步函數將暫停執行直到該promise得以解決。

          異步回調函數和異步函數是不同的術語。

          異步回調函數由高階函數以非阻塞方式執行。但是異步函數在等待promise(await <promise>)解析時暫停其執行。

          但是,我們可以將異步函數用作異步回調!

          我們異步函數fetchUserNames()設為單擊按鈕時調用的異步回調:

          const button = document.getElementById('fetchUsersButton');
          
          button.addEventListener('click', fetchUserNames);
          

          總結

          回調是一個可以作為參數接受并由另一個函數(高階函數)執行的函數.

          有兩種回調函數:同步和異步。

          同步回調函數與使用回調函數的高階函數同時執行,同步回調是阻塞的。另一方面,異步回調的執行時間比高階函數的執行時間晚,異步回調是非阻塞的。

          完~,感謝大家的觀看,我是小智,我去刷碗啦!


          作者:Shadeed 譯者:前端小智 來源:dmitripavlutin 原文:https://dmitripavlutin.com/javascript-variables-practices/


          主站蜘蛛池模板: 一本久久精品一区二区| 亚洲欧美日韩一区二区三区在线 | 久久久久人妻精品一区三寸| 国产在线精品一区在线观看| 武侠古典一区二区三区中文| 精品一区二区三区电影| 亚洲国产av一区二区三区丶| 韩国福利视频一区二区| 99久久精品费精品国产一区二区| 成人免费区一区二区三区| 日韩精品无码一区二区三区不卡 | 无码毛片一区二区三区视频免费播放| 一区二区三区观看免费中文视频在线播放 | 乱精品一区字幕二区| 视频一区二区三区在线观看| 大屁股熟女一区二区三区| 国产精品无圣光一区二区| 国产视频福利一区| 亚洲福利秒拍一区二区| 色妞AV永久一区二区国产AV| 欧美激情国产精品视频一区二区 | 熟女少妇丰满一区二区| 精品国产AV一区二区三区| 国产综合精品一区二区三区| 丰满人妻一区二区三区视频| 亚洲一区二区三区在线观看蜜桃| 亚洲视频一区二区三区四区| 一区二区三区内射美女毛片| 国产精品高清视亚洲一区二区| 精品久久国产一区二区三区香蕉| 亚洲一区二区三区国产精品无码| 国产精品一区二区综合| 怡红院美国分院一区二区| 国产成人一区二区三区免费视频| 另类一区二区三区| 色婷婷综合久久久久中文一区二区| 精彩视频一区二区三区| 国产精品高清一区二区三区| 国产传媒一区二区三区呀| 亚洲一区无码精品色| 国产精品无码一区二区三级 |