把位元轉換成浮點數例如:
var iNum1 = 25;//25 等於 00000000000000000000000000011001var iNum2 = ~iNum1;//轉換為 11111111111111111111111111100110alert(iNum2);//輸出 "-26"
位元運算 NOT 實質上是對數字求負,然後減 1,因此 25 變 -26。用下面的方法也可以得到同樣的方法:
var iNum1 = 25;var iNum2 = -iNum1 -1;alert(iNum2);//輸出 -26
AND運算(&)與運算 AND 由和號(&)表示。它把每個數字中的數位對齊,然後用下面的規則對同一位置上的兩個數位進行 AND 運算(若且唯若兩個數位都是1時才返回1):
| 第一個數字中的數位 |
第二個數字中的數位 |
結果 |
| 1 |
1 |
1 |
| 1 |
0 |
0 |
| 0 |
1 |
0 |
| 0 |
0 |
0 |
例如,要對數字 25 和 3 進行 AND 運算,代碼如下所示:
var iResult = 25 & 3;alert(iResult);//輸出 "1"
25 和 3 進行 AND 運算的結果是 1。為什嗎?分析如下:
25 = 0000 0000 0000 0000 0000 0000 0001 1001 3 = 0000 0000 0000 0000 0000 0000 0000 0011---------------------------------------------AND = 0000 0000 0000 0000 0000 0000 0000 0001
可以看出,在 25 和 3 中,只有一個數位(位 0)存放的都是 1,因此,其他數位產生的都是 0,所以結果為 1。
OR運算(|)或運算 OR 由符號(|)表示。在計算每位時,OR 運算子採用下列規則(若且唯若兩個數位都是0時才返回0):
| 第一個數字中的數位 |
第二個數字中的數位 |
結果 |
| 1 |
1 |
1 |
| 1 |
0 |
1 |
| 0 |
1 |
1 |
| 0 |
0 |
0 |
仍然使用 AND 運算子所用的例子,對 25 和 3 進行 OR 運算,代碼如下:
var iResult = 25 | 3;alert(iResult);//輸出 "27"
25 和 3 進行 OR 運算的結果是 27:
25 = 0000 0000 0000 0000 0000 0000 0001 1001 3 = 0000 0000 0000 0000 0000 0000 0000 0011--------------------------------------------OR = 0000 0000 0000 0000 0000 0000 0001 1011
可以看出,在兩個數字中,共有 4 個數位存放的是 1,這些數位被傳遞給結果。二進位代碼 11011 等於 27。
XOR運算(^)異或運算 XOR 由符號(^)表示。XOR 不同於 OR,當有且只有一個數位存放的是 1 時,它才返回 1。真值表如下:
| 第一個數字中的數位 |
第二個數字中的數位 |
結果 |
| 1 |
1 |
0 |
| 1 |
0 |
1 |
| 0 |
1 |
1 |
| 0 |
0 |
0 |
對 25 和 3 進行 XOR 運算,代碼如下:
var iResult = 25 ^ 3;alert(iResult);//輸出 "26"
25 和 3 進行 XOR 運算的結果是 26:
25 = 0000 0000 0000 0000 0000 0000 0001 1001 3 = 0000 0000 0000 0000 0000 0000 0000 0011---------------------------------------------XOR = 0000 0000 0000 0000 0000 0000 0001 1010
可以看出,在兩個數字中,共有 4 個數位存放的是 1,這些數位被傳遞給結果。二進位代碼 11010 等於 26。
左移運算(<<)左移運算由兩個小於符號表示(<<)。它把數字中的所有數位向左移動指定的數量。例如,把數字 2(等於二進位中的 10)左移 5 位,結果為 64(等於二進位中的 1000000):
var iOld = 2;//等於二進位 10var iNew = iOld << 5;//等於二進位 1000000 十進位 64
注意:在左移數位時,數字右邊多出 5 個空位。左移運算用 0 填充這些空位,使結果成為完整的 32 位元字。
注意:左移運算保留數位符號位。例如,如果把 -2 左移 5 位,得到的是 -64,而不是 64。“符號仍然儲存在第 32 位中嗎?”是的,不過這在 ECMAScript 後台進行,開發人員不能直接存取第 32 個數位。即使輸出二進位字串形式的負數,顯示的也是負號形式(例如,-2 將顯示 -10。)
右移運算(>>)有符號右移運算有符號右移運算子由兩個大於符號表示(>>)。它把 32 位元字中的所有數位整體右移,同時保留該數的符號(正號或負號)。有符號右移運算子恰好與左移運算相反。例如,把 64 右移 5 位,將變為 2:
var iOld = 64;//等於二進位 1000000var iNew = iOld >> 5;//等於二進位 10 十進位 2
同樣,移動數位後會造成空位。這次,空位位於數位左側,但位於符號位之後。ECMAScript 用符號位的值填充這些空位,建立完整的數字,如所示:
無符號右移運算無符號右移運算子由三個大於符號(>>>)表示,它將無符號 32 位元的所有數位整體右移。對於正數,無符號右移運算的結果與有符號右移運算一樣。
用有符號右移運算中的例子,把 64 右移 5 位,將變為 2:
var iOld = 64;//等於二進位 1000000var iNew = iOld >>> 5;//等於二進位 10 十進位 2
對於負數,情況就不同了。
無符號右移運算用 0 填充所有空位。對於正數,這與有符號右移運算的操作一樣,而負數則被作為正數來處理。
由於無符號右移運算的結果是一個 32 位的正數,所以負數的無符號右移運算得到的總是一個非常大的數字。例如,如果把 -64 右移 5 位,將得到 134217726。如何得到這種結果的呢?
要實現這一點,需要把這個數字轉換成無符號的等價形式(儘管該數字本身還是有符號的),可以通過以下代碼獲得這種形式:
var iUnsigned64 = -64 >>> 0;
然後,用 Number 類型的 toString() 擷取它的真正的位表示,採用的基為 2:
alert(iUnsigned64.toString(2));
這將產生 11111111111111111111111111000000,即有符號整數 -64 的二進位補碼錶示,不過它等於不帶正負號的整數 4294967232。
出於這種原因,使用無符號右移運算子要小心。
邏輯運算邏輯運算分為兩種,一種會改變目標資料類型,另一種則不會。前者的典型代表是邏輯非運算,無論運算元是什麼類型,執行邏輯非運算後,都會被轉化為bool值。例如:var a = "123";var b = !a; // false
而另一種形式則不改變目標類型,且支援布爾短路,包括“邏輯與”(&&)和“邏輯或”(||)運算。所謂布爾短路,指的是指判斷第一個運算元就決定運算結果,而不需要處理第二個運算元。具體運算規則如下:第一個運算元為真時,邏輯或運算返回第一個運算元(注意,沒有改變類型),邏輯與運算返回第二個運算元第一個運算元為假時,邏輯或運算返回第二個運算元,邏輯與運算返回第一個運算元我們來舉幾個特殊點的例子:function and(a, b) { return a && b;}function or(a, b) { return a || b;}var a = and("str", false); // a === falsevar b = or("str", false); // b === "str"var c = and(0, "str2"); // c === 0var d = or(0, "str2"); // d === "str2"這種運算最常見的用法是處理實參。我們知道,JavaScript中的實參列表和形參列表可以長度不等,那麼,如何處理不等的部分呢?我們舉個例子:function add(a, b) { return a + b;}var a = add(5); // NaN結果是NaN,這明顯不是我們想要的結果,我們更願意它返回5。我們可以利用邏輯運算:function add(a, b) { b = b || 0; return a + b;}var a = add(5); // 5var b = add(5, 2); // 7如果形參長度大於實參長度,超過的部分將是undefined。而b = b || 0這句能在b為undefined(布爾值為false)的時候,把0賦給b,使得b仍然為數值類型,並參與運算。當然,這樣處理還是很簡陋的,比如當傳入的b為非Null 字元串的時候,這個函數還是會出錯,所以正確的做法應該是判斷是不是數值類型,但在排除API使用者亂來的情況下,邏輯運算不失為一種好辦法。
字串運算JavaScript中,有且只有一種字串運算,那就是字串串連。當然,字串也可以參與其他運算,比如比較、等值、賦值等運算,但我們把它們放到其他分類去講。string類型裡內建的方法,例如切割字串等等,也不屬於我們這裡講的運算式運算。字串串連運算對應的運算子號是“+”。請注意,“+”是一個多義性符號,它既可以用於數值加法運算,也可以用於一元運算子,還能用於字串串連。具體用於那種運算,由運算元的數量和類型決定。當存在兩個或以上的運算元,且開頭兩個運算元其中一個是字串類型時,會將其他非字串的轉化為字串,目標類型為字串。例如:var a = "str" + "ing"; // a === "string"var b = "str" + 0; // b === "str0"var c = 0 + "str"; // c === "0str"var d = "str" + undefined; // d === "strundefined"var e = null + "str" + undefined; // e === "nullstrundefined"var f = null + undefined + "str"; // f == NaN
比較運算等值檢測等值檢測的目的在於判斷兩個變數是否相同或相等。我們說相同與不相同,是指運算子“===”和“!==”的運算效果;說相等與不相等,是指運算子“==”和“!=”的運算效果。我們可以用個表格來表示:
比較運算中的等值檢測
| 名稱 |
運算子 |
說明 |
| 相等 |
== |
比較兩個運算式,看是否相等 |
| 不等 |
!= |
比較兩個運算式,看是否不相等 |
| 嚴格相等 |
=== |
比較兩個運算式,看值是否相等並具有相同的資料類型 |
| 不嚴格相等 |
!== |
比較兩個運算式,看是否具有不相等的值或資料類型不同 |
等值檢測中相等運算規則
等值檢測中的相等運算規則
| 類型 |
運算規則 |
| 兩個值類型進行比較 |
轉換成相同資料類型的值進行資料等值比較 |
| 值類型與參考型別比較 |
將參考型別的資料轉換為值類型,再進行資料等值比較 |
| 兩個參考型別比較 |
比較引用的地址 |
對值類型和參考型別概念模糊的可以去看之前的JavaScript變數一文。等值檢測中相同運算規則
等值檢測中相同運算規則
| 類型 |
運算規則 |
| 兩個值類型進行比較 |
資料類型不同,則必然不相同 資料類型相同時,進行數值等值比較 |
| 值類型與參考型別比較 |
必然不相同 |
| 兩個參考型別比較 |
比較引用的地址 |
我們可以看到,兩個參考型別比較,相同和相等並沒有什麼區別。我們看個例子:var str1 = new String("str");var str2 = new String("str");console.log(str1 == str2); // falseconsole.log(str1 === str2); // false序列檢測序列檢測這個概念咋一聽很拗口,換個說法其實就是比較大小。比較的運算子有四個:>、>=、<、<=,意義不用說大家都明白。可以進行序列檢測的資料類型有三種,boolean、string和number。它們的序列值如下表所示:
| 可比較序列的類型 |
序列值 |
| boolean |
0~1 |
| string |
0~255(*注1) |
| number |
NEGATIVE_INFINITY~POSITIVE_INFINITY(*注2) |
*注1:在一般語言中,字元(char)這種資料類型是按ASCII碼排序的。JavaScript中不存在字元類型,但字串中的每一個字元,都將作為單一字元參與序列檢測。*注2:表示負無窮到正無窮,實際上是有界限的,只不過這個界限達到了10^308層級(可以通過Number.MAX_VALUE查看),我們一般認為達不到。值NaN沒有序列值,任何值(包括NaN本身)與NaN進行序列檢測都將得到false序列檢測的運算規則如下表:
序列檢測的運算規則
| 類型 |
運算規則 |
| 兩個值類型進行比較 |
直接比較資料在序列中的大小 |
| 值類型與參考型別比較 |
將參考型別的資料轉換為值類型資料,再比較資料在序列中的大小 |
| 兩個參考型別比較 |
無意義,總是返回false |
函數調用這部分內容在上一節的JavaScript函數中有詳細解說,就不細表了。有一點要說的是,運算子“( )”,只能在函數或指向某函數的變數後,否則,將會觸發異常。
特殊作用的運算子在JavaScript中有一些運算子,不直接產生運算效果,而是用於影響運算效果,這一類運算子的操作對象通常是“運算式”,而非“運算式的值”。另外的一些運算子不直接針對變數的值運算,而是針對變數運算。詳細的運算子和它們的作用如下表:
| 目標 |
運算子 |
作用 |
備忘 |
| 運算元 |
typeof |
返回表示資料類型的字串 |
|
| 運算元 |
instanceof |
返回繼承關係 |
|
| 運算元 |
in |
返回成員關係 |
|
| 運算元 |
delete |
刪除成員 |
|
| 運算式 |
void |
避免運算式返回值 |
使運算式總是返回值undefined |
| 運算式 |
?: |
按條件執行兩個運算式之一 |
也稱三目條件運算子 |
| 運算式 |
() |
運算式分組和調整運算次序 |
也稱優先順序運算子 |
| 運算式 |
, |
運算式順序地連續執行 |
也稱多重求值或逗號運算子 |
運算優先順序運算優先順序在複雜運算中有著舉足輕重的作用,例如我們看個運算式:void 1+2
我們知道void的作用是讓運算式總是返回undefined,那麼,void操作的對象究竟是1還是1+2呢?換句話說,void和+哪個的優先順序更高?我們不妨假設,如果void的優先順序更高,那麼,void操作的數將是1,操作結果變成( void 1 ) + 2,也就是undefined+2,結果將是NaN。而如果相反,+的優先順序更高,那麼,結果將是void (1 + 2),也就是void 3也就是undefined。那麼,究竟是哪種呢?事實是NaN,也就是說,void的優先順序更高。我們將詳細列出JavaScript中常見的運算子及它們的優先關係。注意,表格從上到下,優先順序越來越低。
JavaScript中運算子的優先順序
| 優先順序 |
運算子 |
描述 |
| 最高 |
. [ ] ( ) |
對象成員存取 數組下標 函數調用 |
| 從 |
++ - ~ ~ delete new typeof void |
一元運算子 |
| 上 |
* / % |
乘法 除法 模數 |
| 到 |
+ - + |
加法 減法 字串串連 |
| 下 |
<< >> >>> |
移位 |
| 的 |
< <= > >= instanceof |
序列檢測 繼承關係 |
| 優 |
== != === !== |
等值檢測 |
| 先 |
& |
按位與 |
| 級 |
^ |
按位異或 |
| 會 |
| |
按位或 |
| 越 |
&& |
邏輯與 |
| 來 |
|| |
邏輯或 |
| 越 |
?: |
三元條件 |
| 低 |
= op= |
賦值 運算賦值 |
| 最低 |
, |
多重求值 |
同一優先順序的不同或相同運算子同時出現在一個語句中時,按從左至右執行。當然,類似CSS中的!important,JavaScript中也有一個強制改變優先順序的符號,就是( ),括弧內的運算會優先於括弧外的運算。