在程式語言的分類上,有所謂強型別(Strong type)、弱型別(Weak type)語言,強弱之別是相對的,沒有絕對之分野。
Java偏向強型別語言,在Java中運算或操作,較少有自動之型態轉換,舉例來說,字串就是字串,在Java中絕不可能直接作以下之操作:
String number1 = "3";
String number2 = "2";
int result = number1 - number2;
String number2 = "2";
int result = number1 - number2;
在強型別中,型態轉換或剖析必須明確操作。例如:
String number1 = "3";
String number2 = "2";
int result = Integer.parseInt(number1) - Integer.parseInt(number2);
String number2 = "2";
int result = Integer.parseInt(number1) - Integer.parseInt(number2);
JavaScript是弱型別語言,字串的減法操作卻是可行的:
js> var number1 = '3';
js> var number2 = '2';
js> var result = number1 - number2;
js> result;
1
js> typeof result;
number
js>
js> var number2 = '2';
js> var result = number1 - number2;
js> result;
1
js> typeof result;
number
js>
強型別語言必須明確進行型態轉換或剖析,避免了許多非預期的型態轉換錯誤,然而帶來了語法上的冗長,弱型別語言則相反,取得了語法簡潔的優點,但必須多注意非預期型態轉換的問題。
JavaScript的基本型態number、string與boolean,會在必要的時候,自動型態轉換為對應的包裹物件Number、String與Boolean。例如:
js> var num = 10;
js> var binary = num.toString(2);
js> binary;
1010
js> var binary = (10).toString(2);
js> binary;
1010
js>
js> var binary = num.toString(2);
js> binary;
1010
js> var binary = (10).toString(2);
js> binary;
1010
js>
num變數指定的10型態是number,但在作toString()操作時則是物件方有的方法,此時會自動使用 Number實例來包裹10這個number,因此你才可以操作toString()。如果是實字表示,則可以加上()後直接操作toString(), 同樣會為你自動進行型態轉換。
類似地,在對string作操作時,若必要,也會自動包裹為String的實例。例如:
js> var text = 'caterpillar';
js> text.toUpperCase();
CATERPILLAR
js> 'caterpillar'.toUpperCase();
CATERPILLAR
js>
js> text.toUpperCase();
CATERPILLAR
js> 'caterpillar'.toUpperCase();
CATERPILLAR
js>
toUpperCase()是String上定義的方法,執行環境必要時,會將string使用String包裹,才讓你操作toUpperCase()方法。
你可以直接建立包裹物件。例如:
js> var num = new Number(10);
js> var text = new String('caterpillar');
js> typeof 10;
number
js> typeof num;
object
js> typeof 'caterpillar';
string
js> typeof text;
object
js>
js> var text = new String('caterpillar');
js> typeof 10;
number
js> typeof num;
object
js> typeof 'caterpillar';
string
js> typeof text;
object
js>
關於Number、String與Boolean上可操作的方法,可參考:
你也可以使用parseInt()、parseFloat()將字串轉換為數值,其好處是會自動忽略字串尾端非數字部份。例如:
js> parseInt('10 years old...XD');
10
js> parseFloat('3.14159......');
3.14159
js> parseInt('010', 10)
10
js> parseInt('010', 8)
8
js>
10
js> parseFloat('3.14159......');
3.14159
js> parseInt('010', 10)
10
js> parseInt('010', 8)
8
js>
後兩個parseInt()分別指定了基數為10進位或8進位,如果字串以0x開頭,基數預設為16進位,以0開頭,建議指定基數為10或8進位,其它字串則預設為10進位。
對於字串,如果代表數字的話,可使用+、-、*、/來作運算,不過要注意,+優先作字串的串接,而非轉換為數字作加法,-、*、/則會轉換為數字。例如:
js> '6' + '2'
62
js> '6' - '2'
4
js> '6' * '2'
12
js> '6' / '2'
3
js>
62
js> '6' - '2'
4
js> '6' * '2'
12
js> '6' / '2'
3
js>
在JavaScript中若結合布林值作+、-、*、/等運算,true會被當作1,而false會被當作0。例如:
js> 1 + true;
2
js> 1 + false;
1
js>
2
js> 1 + false;
1
js>
布林值很有趣,在真假判斷式中,所有東西都可以轉換為布林值。一個口訣是:除了0、NaN、''、null、undefinied是假的(false)之外,其它都是真的(true)。這些就是所謂False Family成員。
例如,若物件上不存在某個特性,直接取用該特性會得到undefined的值,所以若想知道某物件上是否存在該特性,則可以如下:
js> function exist(obj) {
> if(obj.x) {
> print('x exists.');
> } else {
> print('x doesn\'t exist.');
> }
> }
js> var o = {};
js> exist(o);
x doesn't exist.
js> o.x = 10;
10
js> exist(o);
x exists.
js>
> if(obj.x) {
> print('x exists.');
> } else {
> print('x doesn\'t exist.');
> }
> }
js> var o = {};
js> exist(o);
x doesn't exist.
js> o.x = 10;
10
js> exist(o);
x exists.
js>
在if中,如果取得undefined,則會當作false。如果你想避免x被設為0、NaN、''、null而造成誤判,則可以作更嚴格的檢查。例如:
js> function exist(obj) {
> if(typeof(obj.x) != 'undefined') {
> print('x exists.');
> } else {
> print('x doesn\'t exist.');
> }
> }
js> var o = { x : 0 };
js> exist(o);
x exists.
js>
> if(typeof(obj.x) != 'undefined') {
> print('x exists.');
> } else {
> print('x doesn\'t exist.');
> }
> }
js> var o = { x : 0 };
js> exist(o);
x exists.
js>
型態轉換也會發生在相等性比較時,在JavaScript中有兩個相等性運算子==與===,都可以判斷值或物件參考是否相同,簡單來說,前者會嘗試將==兩邊轉換為同一型態,再比較是否相等,但後者只要===兩邊型態不一,就會判斷為false。例如:
js> '' == 0;
true
js> '' === 0;
false
js> null == undefined;
true
js> null === undefined;
false
js> 1 == true;
true
js> 1 === true;
false
js>
true
js> '' === 0;
false
js> null == undefined;
true
js> null === undefined;
false
js> 1 == true;
true
js> 1 === true;
false
js>
簡單來說,==執行較寬鬆的比較,可允許型態轉換後的比較,===執行較嚴格的比較,型態必須相同才有可能為true(當然!!=與!==則是相反的操作)。不過,不確定時還是作測試來得好。例如:
js> false == undefined;
false
js>
false
js>
在弱型別語言中,型態轉換往往自動發生,最好還是實際測試了解結果,避免不必要的型態轉換而發生誤判或錯誤的運算結果。以上例而言,你還可以明確指定轉換:
js> false == Boolean(undefined);
true
js>
true
js>