parseInt()這個函數在前端檢查滿常被使用
一般使用parseInt()函數大都會忽略傳入進制的基數
導致parseInt()運算完的結果不是預先期待值
例如 parseInt('08') ,預先期待值大都會是十進位的 8
但得到的結果值確是 0
這是為什麼呢?
在使用parseInt()函數時若沒有使用基數參數
parseInt會根據傳入字串的頭碼(8進)或頭二碼(16進至36進)來作預設基數的參考
一般的高階語言數值表示式會使用頭碼或頭二碼來作該數值的進制
01234 代表8進制
12345 代表10進制
0x123 代表16進制以上
parseInt('08')會回傳 0
是因頭碼為0所以parseInt()會指定使用8進制格式進行運算
第二碼 8 則超過8進制的上限值7,所以該函數就只回傳 0
8 以後的文數字都會被捨棄
節錄 Rhino Javascript 1.6R7 版中該函數實作程式碼
//如果未傳入基數,radix = 0
final int NO_RADIX = -1;
if (radix == 0) {
radix = NO_RADIX; //沒有使用基數
} else if (radix <> 36) { // 如果不是2進位到36進位回傳 NaN
return ScriptRuntime.NaNobj;
} else if (radix == 16 && len - start > 1 && s.charAt(start) == '0') {
c = s.charAt(start+1);
if (c == 'x' || c == 'X')
start += 2; //16進位
}
if (radix == NO_RADIX) {
radix = 10; //指定為10進制
if (len - start > 1 && s.charAt(start) == '0') { //如果頭碼是 0 進行基數檢查
c = s.charAt(start+1);
if (c == 'x' || c == 'X') { //如果頭2碼是0x代表16進制
radix = 16;
start += 2;
} else if ('0' <= c && c <= '9') { //八進制
radix = 8;
start++;
}
}
}
接著進行數字演算
int end;
double sum = 0.0; //數字運算後總值
for (end=start; end < len; end++) {
char c = s.charAt(end);
int newDigit;
//關鍵在此,傳入的字串內容是 08
//第一碼取得 0 ,加總後還是0
//第二碼取得 8 ,但使用的基數為8進制
//迴圈進行到第2碼即中止回傳目前的 sum
if ('0' <= c && c <= digitMax) //8進制 digitMax 會是 7
newDigit = c - '0';
else if ('a' <= c && c < lowerCaseBound)
newDigit = c - 'a' + 10;
else if ('A' <= c && c < upperCaseBound)
newDigit = c - 'A' + 10;
else
break;
sum = sum*radix + newDigit;
}
沒有留言:
張貼留言