對於運算子的使用,最主要是要注意自動型態轉換的問題,其中有關+、-、*、/以及==及===(!=與!==)的說明,在 型態轉換 有先作過一些說明。
當+兩邊的運算元有一個是字串時,就會作字串的串接,而整個運算式中有數字也有字串時,要注意運算順序。例如:
js> 1 + 2 + '3';
33
js> '1' + 2 + 3;
123
js> '1' + (2 + 3);
15
js>
33
js> '1' + 2 + 3;
123
js> '1' + (2 + 3);
15
js>
第一個式子是先作1+2的運算,結果再與'3'作字串的串接,得到'33'的字串;第二個式子是先作字串的串接,得到'12',再與3作字串的串接,得到'123'的字串;不確定的話,可如第三個式子,使用()定義優先運算順序。
在比較運算上,除了 型態轉換 中提到的使用==、===、!=、!==之,還可以使用>、>=、<、<=,在JavaScript中,這些運算子不僅可用在比較數字,還可以用來比較字串,如果運算子兩邊都是字串,則逐字元依Unicode編碼數值進行比較。
但如果>、>=、<、<=兩邊一個是字串,一個是數字,那麼型態轉換又有可能自動發生。如果字串的部份代表數字,則會轉換為數字,再與另一數字進行比較。如果字串的部份不代表數字,則會被轉換為NaN,與另一數字比較的結果自然就是false。
>、>=、<、<=兩邊其實可用於物件,如果物件有可能轉換為數字,視物件有無valueOf()方法,且傳回數字,則以傳回的數字相比。例如Date就是一個例子:
js> var date = new Date();
js> date.valueOf();
1289293581594
js> date > 1289293581594;
false
js> date > 1289293581593;
true
js> date > new Date();
false
js> new Date() > date;
true
js> var obj = {
> valueOf : function() {
> return 100;
> }
> };
js> 1 + obj;
101
js> 1 > obj;
false
js>
js> date.valueOf();
1289293581594
js> date > 1289293581594;
false
js> date > 1289293581593;
true
js> date > new Date();
false
js> new Date() > date;
true
js> var obj = {
> valueOf : function() {
> return 100;
> }
> };
js> 1 + obj;
101
js> 1 > obj;
false
js>
正如上例所示,其它運算式若需轉為數值,也是透過valueOf()取得值。
預設valueOf()會傳回toString()的傳回值。如果你沒有重新定義valueOf(),就會使用toString()的傳回值作比較。
js> var o1 = {};
js> o1.valueOf();
[object Object]
js> var o2 = {};
js> o2;
[object Object]
js> o1 >= o2;
true
js> o1 > o2;
false
js> o1 == o2;
false
js>
js> o1.valueOf();
[object Object]
js> var o2 = {};
js> o2;
[object Object]
js> o1 >= o2;
true
js> o1 > o2;
false
js> o1 == o2;
false
js>
注意,==用來比較物件時,是比較是否參考同一物件。
如果你要測試某個物件上是否有某個特性,且要傳回true、false的結果,則可以使用in運算子。例如:
js> var obj = { x : 10 };
js> 'x' in obj;
true
js>
js> 'x' in obj;
true
js>
之後還會詳細介紹物件,在這邊也可以看到,物件上的特性名稱,實際上是個字串。
如果你想要得知某個物件是否由哪個建構式(Constructor,或所謂的class)所產生,則可以使用instanceof運算式。例如:
js> [] instanceof Array;
true
js> [] instanceof Object;
true
js> [] instanceof Date;
false
js>
true
js> [] instanceof Object;
true
js> [] instanceof Date;
false
js>
對於沒有繼承關係的,instanceof會傳回false。
typeof也用來測試物件型態,傳回值是字串,對於基本資料型態,數值會傳回'number'、字串會傳回'string'、布林會傳回 'boolean'、對於Function實例會傳回'function'、對於undefined會傳回'undefined'、對於其它物件一律傳回 'object',包括null也是傳回'object'。
js> typeof 1;
number
js> typeof '';
string
js> typeof true;
boolean
js> typeof function() {};
function
js> typeof undefined;
undefined
js> typeof {};
object
js> typeof null;
object
js>
number
js> typeof '';
string
js> typeof true;
boolean
js> typeof function() {};
function
js> typeof undefined;
undefined
js> typeof {};
object
js> typeof null;
object
js>
&& 與 ||大家都知道用來判斷AND與OR是否成立,而且具有捷徑運算,例如&&只要左運算元可以判斷為不成立,則&&結果直 接不成立,不用判斷右運算元,而||只要左運算元判斷為成立,就直接判斷||結果為成立,不用再判斷右運算元。
不過,&&或||其傳回值並非true或false,而是在判斷式整個可以確認是否成立時,傳回當時的運算元。例如:
js> 'left' && 'right';
right
js> 0 && 'right';
0
js> 'left' && 0;
0
js>
right
js> 0 && 'right';
0
js> 'left' && 0;
0
js>
在 上面第一個例子中,左運算元非空字串,會當作結果成立,所以再判斷右運算元,也非空字串,所以判斷整個&&成立,由於是停在第二個運算 元,所以傳回'right'。第二個例子,由於0會被當作不成立,此時不用判斷右運算元,就可判斷整個&&運算不成立,所以直接傳回0。 第三個例子,由於左運算元非空字串,會當作結果成立,所以再判斷右運算元為0,所以當作不成立,整個&&運算此時確認不成立,傳回右運算元。
||的例子則如下:
js> 'right' || 'left';
right
js> 0 || 'left';
left
js> 'right' || 0;
right
js>
right
js> 0 || 'left';
left
js> 'right' || 0;
right
js>
這個特性很有用,例如,想要在某個值存在時直接使用,而不存在時提供預設值,則可以如下:
js> function doSome(arg) {
> var option = arg || 'default';
> print(option);
> }
js> doSome();
default
js> doSome('caterpillar');
caterpillar
js>
> var option = arg || 'default';
> print(option);
> }
js> doSome();
default
js> doSome('caterpillar');
caterpillar
js>
上面用到了函式作為範例,之後還會詳細說明,像是如果函式參數很多時,還可以合併物件的方式提供預設值。上例其實就相當於使用?:運算子的結果:
js> function doSome(arg) {
> var option = arg ? arg : 'default';
> print(option);
> }
js> doSome();
default
js> doSome('caterpillar');
caterpillar
js>
> var option = arg ? arg : 'default';
> print(option);
> }
js> doSome();
default
js> doSome('caterpillar');
caterpillar
js>
兩者可以達到相同的效果,不過慣例上還是使用||的方式。
void運算子放在任何資料或運算式之前,都會產生undefined,這是取得undefined的另一個方式,在一些無法直接在程式中寫undefined來取得undefined值的環境中,可以使用void來取得。例如:
js> void 0;
js> typeof void 0;
undefined
js>
js> typeof void 0;
undefined
js>