在 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 轉為字符串。
.
