在 JavaScript 中聲明變量不需指定類型,對變量賦值也沒有類型檢查,同時還允許隱式類型轉換。 這些特征說明 JavaScript 屬於弱類型的語言。
在強類型的 C++ 中,多數情況下構造函數需要聲明為 explicit
來禁止隱式類型轉換, 避免誤用(見Item 15:資源管理類需要提供對原始資源的訪問)。 弱類型的 JavaScript 中沒有這一機制,比如下面的代碼:
// 彈出對話框中輸入1 var a = prompt('input a number'); var b = a + 1; console.log(b); // 控制台輸出 11
目前 JavaScript 還無法阻止 a
被隱式轉換為字符串。 本文便來總結一下 JavaScript 的類型轉換行為,以及隱式類型轉換的規則。
轉換為字符串
轉換為字符串是應用程序中的常見操作,幾乎所有語言都提供了將任何類型轉換為字符串的通用接口。 比如Java和C#的toString
方法、C++的函數std::to_string
,當然還有JavaScript的toString
方法。
多數的JavaScript宿主環境(比如Node.js和Chrome)都提供了全局函數toString
; 與此同時Object.prototype
也定義了toString
方法,使得所有對象都擁有轉換為字符串的能力。
比如一個Number
轉換為String
:
var n = 1; n.toString(); // '1'
toString
接受一個參數指定進制,默認為10. 可以利用這個參數生成包括字母和數字的隨機字符串:
Math.random().toString(36).substr(2);
random
生成一個0到1的隨機數,36進制的字符集為[0-9a-z]
(36個),substr
用來截掉起始的"0."
。 另外Object.prototype.toString
可以用來檢測JavaScript對象的類型:
var toString = Object.prototype.toString; toString.call(new Date); // [object Date] toString.call(new String); // [object String] toString.call(Math); // [object Math] // Since JavaScript 1.8.5 toString.call(undefined); // [object Undefined] toString.call(null); // [object Null] // 自定義類型 toString.call(new MyClass); // [object Object]
轉換為數字
字符串轉換為數字也是常見需求,通常用來從用戶輸入或文件來獲得一個Number
。 在C++中可以用atoi
、cin
、scanf
等函數,在JavaScript中可以直接用parseInt
和parseFloat
。 例如:
var iNum1 = parseInt("12345red"); //返回 12345 var iNum1 = parseInt("0xA"); //返回 10 var iNum1 = parseInt("56.9"); //返回 56 var iNum1 = parseInt("red"); //返回 NaN var fNum4 = parseFloat("11.22.33"); //返回 11.22
注意NaN
是JavaScript中唯一一個不等於自己的值。(NaN == NaN) === false
! 如果遇到非法字符,parseInt
和parseFloat
會忽略之后的所有內容。
parseFloat
只接受十進制數字的字符串,而parseInt
還提供了第二個參數(可選)用來指定字符串表示數字的進制:
var iNum1 = parseInt("10", 2); //返回 2 var iNum2 = parseInt("10", 8); //返回 8 var iNum3 = parseInt("10", 10); //返回 10
上述例子來自 w3school.com.cn: http://www.w3school.com.cn/js/pro_js_typeconversion.asp
強制類型轉換
強制類型轉換在C++中有兩種方式:用括號將類型聲明在變量之前;或者調用構造函數。 在JavaScript中沒有類型關鍵字(只有一個var
來聲明變量),因而只能調用構造函數:
Boolean(0) // => false - 零 Boolean(new object()) // => true - 對象 Number(undefined) // => NaN Number(null) // => 0 String(null) // => "null"
隱式類型轉換
隱式類型轉換是最為隱蔽的地方,不加注意的話很容易在這一點上出錯,對這一點的掌握也體現了JavaScript程序員經驗。 JavaScript會自動轉換表達式中對象的類型以完成表達式求值。
四則運算
加法運算符+
是雙目運算符,只要其中一個是String
類型,表達式的值就是一個String
, 會隱式調用每個元的 .toString()
方法。
對於其他的四則運算,只有其中一個是Number
類型,表達式的值便是一個Number
。
對於非法字符的情況通常會返回NaN
:
'1' * 'a' // => NaN,這是因為parseInt(a)值為NaN,1 * NaN 還是 NaN
不同類型的相加的行為比較復雜,也不一致,可以參考這里: https://www.andronio.me/2017/10/22/js-operators-incensistency/
判斷語句
判斷語句中的判斷條件需要是Boolean
類型,所以條件表達式會被隱式轉換為Boolean
。 其轉換規則同Boolean
的構造函數。比如:
var obj = {}; if(obj){ while(obj); }
toString
有些接口只支持字符串參數,會對傳入值進行 toString
。 比如 JavaScript 宿主環境提供的接口:
alert({a: 1}); // => [object Object]
這里傳入任何對象都會被 toString
轉為字符串。
.