回調函數可以用來處理 JavaScript 的異步操作,但是選用 Promise、async/await 更好,因為多重回調函數會導致回調地獄。
回調函數不是**同步的**,它是延時操作執行完畢后會被調用的一個函數。
比如全局方法 "setTimeout" ,它第一個參數就是一個回調函數,第二個參數是等待的時間(以毫秒為單位),如下:
function callback() {
?? console.log("I am the first");
??}
??setTimeout(callback, 300);
??console.log("I am the last");
??// output
??// I am the last
??// I am the first
300毫秒之后,回調函數 callback 會被調用。但是在它完成前,剩下的代碼會繼續往下運行,所以 "I am the last" 會被先打印出來。
開發者常犯的一個錯誤是誤以為回調函數是同步的。比如,他們會把回調函數的返回值用在其他操作上。
例如下面這個錯誤:
function addTwoNumbers() {
?? let firstNumber = 5;
?? let secondNumber;
?? setTimeout(function () {
?? secondNumber = 10;
?? }, 200);
?? console.log(firstNumber + secondNumber);
??}
??addTwoNumbers();
??// NaN
會輸出 "NaN" ,因為 "secondNumber" 還未被賦值。在 "firstNumber + secondNumber" 被執行的時候,"secondNumber" 還沒有被賦值,因為 "setTimeout" 函數要在 "200毫秒" 后才調用回調函數。
最好的解決辦法是把剩下的代碼放在回調函數里去執行:
function addTwoNumbers() {
?? let firstNumber = 5;
?? let secondNumber;
?? setTimeout(function () {
?? secondNumber = 10;
?? console.log(firstNumber + secondNumber);
?? }, 200);
??}
??addTwoNumbers();
??// 15