最簡單又暴力的方式。
加 log 的眉角?
一般會把 log 加在你覺得「最有可能出問題的地方」,但如果一時想不到該加在哪裡,有一個最簡單的方式:通通給他加爆。
把你想要得到的資訊都給 log 出來,像是 迴圈次數
,變數值
,進入的條件判斷
等等之類。
案例一
以下是一個判斷質數的函式,但因為邏輯不正確,所以會得到錯誤的結果:
1 2 3 4 5 6 7 8 9 10 11 12
| function isPrime(num) { if (num === 1) return false if (num === 2) return true for(var i=2; i<num; i++) { if(num % i === 0) { return false } else { return true } } } console.log(isPrime(25))
|
為了釐清問題,可以善用 log 來檢查:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function isPrime(num) { console.log('num:', num) if (num === 1) return false if (num === 2) return true for(var i=2; i<num; i++) { console.log('i:', i) if(num % i === 0) { console.log('num % i === 0', num, i) return false } else { console.log('else', num, i) return true } } } console.log(isPrime(25))
|
輸出結果:
1 2 3 4
| num: 25 i: 2 else 25 2 true
|
這時候問題就一目了然了。
當 25
進入迴圈中的條件判斷 num % i === 0
時沒通過,所以進到 else
區塊,這個時候就直接 return true
,25 被視為質數。
但重點來了,質數的定義是「比自己小的所有數字都無法整除」。所以即便 25 不能被 2 整除,也不代表它就是質數,因為還有 3, 4, 5, … 24 可以測試。
所以這個範例的問題在於﹔「else
應該寫在迴圈的外面」,才能得到正確的結果。
案例二
這是我曾經自己把 +=
寫成 =
產生的 bug。
正確的結果應該要是「轉成小寫的字串」:
1 2 3 4 5 6 7 8 9 10
| const str = 'AbCdEFGhijkLMN' var result = '' for(var i=0; i<str.length; i++) { if(str[i] >= 'A' && str[i] <= 'Z') { result = String.fromCharCode(str[i].charCodeAt(0) + 32) } else { result = str[i] } } console.log(result)
|
最後得到的結果是 n
,為什麼?我們來 log 看看:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const str = 'AbCdEFGhijkLMN' var result = '' for(var i=0; i<str.length; i++) { console.log('i:', i) console.log('str:', str[i]) if(str[i] >= 'A' && str[i] <= 'Z') { console.log('>=A and <=Z:', str[i]) result += String.fromCharCode(str[i].charCodeAt(0) + 32) console.log('result:', result) } else { console.log('else:', str[i]) result += str[i] console.log('result:', result) } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| i: 0 str: A >=A and <=Z: A result: a i: 1 str: b else: b result: b
...
i: 13 str: N >=A and <=Z: N result: n
|
從輸出結果就能很清楚的看到問題點,因為每一圈 result
都被 =
給重新賦值,所以在最後一圈的時後 result
被賦值為 n
,得到了最後的結果。
所以正確的作法是用 +=
來做字串拼接,而不是用 =
來重新賦值。
結束!