一元運算子
一元運算子只有一個引數,即要操作的物件或值。它們是 ECMAScript 中最簡單的運算子。
delete 運算子刪除對以前定義的物件屬性或方法的引用。例如:
var obj = new Object(); obj.name = "David"; alert(obj.name); //輸出 "David" delete obj.name; alert(obj.name); //輸出 "undefined"
delete 運算子不能刪除開發者未定義的屬性和方法。例如,下面的程式碼是沒什麼效果的:
delete obj.toString;
即使 toString 是有效的方法名,這行程式碼也會引發錯誤,因為 toString() 方法是原始的 ECMAScript 方法,不是開發者定義的。
delete 還可以用來刪除陣列中的元素(這沒什麼奇怪的,陣列和物件是相通的)
var arr = [2,4,6,8,10]; delete arr[2]; alert(arr[2]);//undefined
void 運算子對任何值返回 undefined。該運算子通常用於避免輸出不應該輸出的值,例如,從 HTML 的 <a> 元素呼叫 JavaScript 函式時。要正確做到這一點,函式不能返回有效值,否則瀏覽器將清空頁面,只顯示函式的結果。例如:
<a href="javascript:window.open('about:blank')">Click me</a>
如果把這行程式碼放入 HTML 頁面,點選其中的連結,即可看到螢幕上顯示 "[object]"。TIY這是因為 window.open() 方法返回了新開啟的視窗的引用。然後該物件將被轉換成要顯示的字串。要避免這種效果,可以用 void 運算子呼叫 window.open() 函式:
<a href="javascript:void(window.open('about:blank'))">A</a> //這使 window.open() 呼叫返回 undefined,它不是有效值,不會顯示在瀏覽器視窗中。
沒有返回值的函式真正返回的都是 undefined。
直接從 C(和 Java)借用的兩個運算子是前增量運算子和前減量運算子。所謂前增量運算子,就是數值上加 1,形式是在變數前放兩個加號(++):
var iNum = 10; ++iNum; //實際上等價於 var iNum = 10; iNum = iNum + 1;
同樣,前減量運算子是從數值上減 1,形式是在變數前放兩個減號(--):
var iNum = 10; --iNum;
在使用字首式運算子時,注意增量和減量運算子都發生在計算表示式之前。考慮下面的例子:
var iNum = 10; --iNum; alert(iNum); //輸出 "9" alert(--iNum); //輸出 "8" alert(iNum); //輸出 "8"
第二行程式碼對 iNum 進行減量運算,第三行程式碼顯示的結果是("9")。第四行程式碼又對 iNum 進行減量運算,不過這次前減量運算和輸出操作出現在同一個語句中,顯示的結果是 "8"。為了證明已實現了所有的減量操作,第五行程式碼又輸出一次"8"。在算術表示式中,前增量和前減量運算子的優先順序是相同的,因此要按照從左到右的順序計算之。例如:
var iNum1 = 2; var iNum2 = 20; var iNum3 = --iNum1 + ++iNum2; //等於 "22" var iNum4 = iNum1 + iNum2;//等於 "22"
還有兩個直接從 C(和 Java)借用的運算子,即後增量運算子和後減量運算子。後增量運算子也是給數值上加 1,形式是在變數後放兩個加號(++):
var iNum = 10; iNum++;
後減量運算子是從數值上減 1,形式為在變數後加兩個減號(--):
var iNum = 10; iNum--;
與字首式運算子不同的是,字尾式運算子是在計算過包含它們的表示式後才進行增量或減量運算的。考慮以下的例子:
var iNum = 10; iNum--; alert(iNum); //輸出 "9" alert(iNum--); //輸出 "9" alert(iNum); //輸出 "8"
在算術表示式中,後增量和後減量運算子的優先順序是相同的,因此要按照從左到右的順序計算之。例如:
var iNum1 = 2; var iNum2 = 20; var iNum3 = iNum1-- + iNum2++; //等於 "22" var iNum4 = iNum1 + iNum2; //等於 "22"
在前面的程式碼中,iNum3 等於 22,因為表示式要計算的是 2 + 20。變數 iNum4 也等於 22,不過它計算的是 1 + 21,因為增量和減量運算都在給 iNum3 賦值後才發生。
大多數人都熟悉一元加法和一元減法,它們在 ECMAScript 中的用法與您高中數學中學到的用法相同。一元加法本質上對數字無任何影響,只用來表示正數,但不能將負數轉換成正數
var num=-10; alert(+num);//-10
但並不是一元加法就一無用處.由於這類的運算子只能作用於數字,因些,當將這些運算子運用於字串時,可以起到將字串轉換成數字的妙效!
var str ="123"; str = +str; alert(typeof str);//number
一元減法也有這樣的效用,但同時,它還會對數字求負!
位運算子
位運算子是在數字底層(即表示數字的 32 個數位)進行操作的。
ECMAScript 整數有兩種型別,即有符號整數(允許用正數和負數)和無符號整數(只允許用正數)。在 ECMAScript 中,所有整數字面量預設都是有符號整數!
有符號整數使用 31 位表示整數的數值,用第 32 位表示整數的符號,0 表示正數,1 表示負數。數值範圍從 -2147483648 到 2147483647。
可以以兩種不同的方式儲存二進位制形式的有符號整數,一種用於儲存正數,一種用於儲存負數。正數是以真二進位制形式儲存的,前 31 位中的每一位都表示 2 的冪,從第 1 位(位 0)開始,表示 20,第 2 位(位 1)表示 21。沒用到的位用 0 填充,即忽略不計。例如,下面展示的是數 18 的表示法。
18 的二進位制版本只用了前 5 位,它們是這個數字的有效位。把數字轉換成二進位制字串,就能看到有效位:
var iNum = 18; alert(iNum.toString(2)); //輸出 "10010"
這段程式碼只輸出 "10010",而不是 18 的 32 位表示。其他的數位並不重要,因為僅使用前 5 位即可確定這個十進位制數值。如下圖所示:
負數也儲存為二進位制程式碼,不過採用的形式是二進位制補碼。計算數字二進位制補碼的步驟有三步:
- 確定該數字的非負版本的二進位制表示(例如,要計算 -18的二進位制補碼,首先要確定 18 的二進位制表示)
- 求得二進位制反碼,即要把 0 替換為 1,把 1 替換為 0
- 在二進位制反碼上加 1
要確定 -18 的二進位制表示,首先必須得到 18 的二進位制表示,如下所示:
0000 0000 0000 0000 0000 0000 0001 0010
接下來,計算二進位制反碼,如下所示:
1111 1111 1111 1111 1111 1111 1110 1101
最後,在二進位制反碼上加 1,如下所示:
1111 1111 1111 1111 1111 1111 1110 1101 1 ----------------------------------------------------------- 1111 1111 1111 1111 1111 1111 1110 1110
因此,-18 的二進位制表示即 1111 1111 1111 1111 1111 1111 1110 1110。記住,在處理有符號整數時,開發者不能訪問 31 位。
然而,把負整數轉換成二進位制字串後,ECMAScript 並不以二進位制補碼的形式顯示,而是用數字絕對值的標準二進位制程式碼前面加負號的形式輸出。例如:
var iNum = -18; alert(iNum.toString(2)); //輸出 "-10010"
這段程式碼輸出的是 "-10010",而非二進位制補碼,這是為避免訪問位 31。為了簡便,ECMAScript 用一種簡單的方式處理整數,使得開發者不必關心它們的用法。另一方面,無符號整數把最後一位作為另一個數位處理。在這種模式中,第 32 位不表示數字的符號,而是值 231。由於這個額外的位,無符號整數的數值範圍為 0 到 4294967295。對於小於 2147483647 的整數來說,無符號整數看來與有符號整數一樣,而大於 2147483647 的整數則要使用位 31(在有符號整數中,這一位總是 0)。把無符號整數轉換成字串後,只返回它們的有效位。
注意:所有整數字面量都預設儲存為有符號整數。只有 ECMAScript 的位運算子才能建立無符號整數。
- 位運算子
- 按位非 NOT
- 按位與 AND
- 按位或 OR
- 按位異或 XOR
- 左移運算 <<
- 有符號右移運算 >>
- 無符號右移運算 >>>
按位非運算子首先將數字轉換成二進位制(32位),然後再對各個數位上的1替換成0,而0則替換成1
var num = 12; /*12轉換成二進位制數為1100,32位形式為 00000000000000000000000000001100 //取該二進位制數的補碼 11111111111111111111111111110011 //-13 */ alert(~num);//-13,輸出仍然以十進位制格式 //按位非實際上是對數字取負,然後再減一
按位與,按位或,按位異或運算子都是先將數字轉換成32位二進位制數,然後對各位進行操作
/* 0 & 0 == 0 1 | 0 == 1 0 & 1 == 0 1 | 1 == 1 1 & 1 == 1 0 | 0 == 0 異或比較特殊,當兩加只有一個是1時返回1,其它返回0 1 ^ 1 == 0 1 ^ 0 == 1 0 ^ 0 == 0 */ var num1 = 12; var num2 = 24; /* 00000000000000000000000000001100 // 12 00000000000000000000000000011000 // 24 ----------------------------------------------------- // & 00000000000000000000000000001000 // 8 */ alert(num1 & num2);// 8 /* 00000000000000000000000000001100 // 12 00000000000000000000000000011000 // 24 ----------------------------------------------------- // | 00000000000000000000000000011100 // 28 */ alert(num1 | num2);// 28 /* 00000000000000000000000000001100 // 12 00000000000000000000000000011000 // 24 ----------------------------------------------------- // ^ 00000000000000000000000000010100 // 20 */ alert(num1 ^ num2);//20 alert(num1 << 4);//將12左移4位,192 /*左移運算子將二進位制數字向左移動N位,空出的位置用0填充,超出32位的截去(不改變第32位) 00000000000000000000000000001100 00000000000000000000000011000000 //192 */ alert(num1 >> 4);//將12有符號右移4位,0 /*有符號右移運算子將二進位制數字向右移動N位,前面空出的位置用0填充(不改變第32位),後面截去N位 00000000000000000000000000001100 //12 00000000000000000000000000000000 //0 */ alert(num1 >>> 4);//將12無符號右移4位,0 /*無符號右移運算子將二進位制數字向右移動N位,前面空出的位置用0填充,後面截去N位 //如果N大於0,第32位總會用0填充,使用無符號右移運算子得到的總是正數 00000000000000000000000000001100 //12 00000000000000000000000000000000 //0,對於正數,有符號右移和無符號右移一樣 */ alert(-num1 >>> 4);//將-12無符號右移4位,268435455 /* 11111111111111111111111111110100 //-12 00001111111111111111111111111111 //268435455 */
Boolean 運算子
Boolean 運算子有三種:NOT(!)、AND(&&) 和 OR(||)。
- 邏輯 NOT 運算子的行為如下:
- 對於0,true,null,NaN,undefined,空字串,返回true
- 對於非0數字,非空字串,非空物件,true,返回false
//下面皆返回true alert(!null); alert(!0); alert(!undefined); alert(!false); alert(!""); alert(!NaN); //下面皆返回false alert(!" "); alert(!true); alert(!(new Object())); alert(!-1);
邏輯非運算子(!)始終返回布林值!
當然,邏輯非運算子還有另外一個用途---〉將其它型別轉換成布林值,例如:
alert(!!NaN);//NaN的邏輯值為false
在 ECMAScript 中,邏輯 AND 運算子用雙和號(&&)表示,邏輯OR運算子有雙豎線表示(||),它們的效用你可能已經很清楚
alert(true && true);//true alert(false && true);//false alert(false && false);//false alert(true || true);//true alert(true || false);//true alert(false || false);//false
然而在ECMAScript中,AND與OR運算子不但可以作用於邏輯值!
alert(34 && String);//將返回34 //但新手對這樣的比較可能很迷惑
ECMAScript中的邏輯與邏輯或運算子又被稱之為"快速與","快速或",或稱之為"短路與","短路或".稱之為短路或快速,是因為它們在測試兩邊條件時(將其轉換成布林值),如果第一個表示式的值已經能夠確定整個表示式值的時候,就不會繼續求下一個表示式的值,直接將這個值返回.比如與操作,如果第一個值轉換為布林是false,那麼不管下個是true還是false,整個表示式的值都會是false,而對於OR運算子,則是如果第一個邏輯值為true,那麼整個表示式的值就定了,就不用判斷第二個條件了,所以,我們應該在AND運算中將最可能是false的條件放在前面,而在OR運算中,則將最有可能是true的條件放在前面,這樣可以提高效率!我們可以用下面的例子來證明這一點:
function fnTrue() { alert(true); return true; } function fnFalse() { alert(false); return false; } //注意是執行兩個函式,將返回值進行比較 var a = fnFalse() && fnTrue();//只會出現一個彈窗,顯示false //a = fnTrue() || fnFalse();//這一步只會出現一個彈窗,顯示true
而對於這兩個操作符的返回值,則只要記住一點:將最後判斷的那個條件的值返回
//AND中第一個為true時,還要繼續判斷,第二個為false,整個表示式的值為false,同時將第二個條件返回 alert(true && false); //當對其它型別使用AND時也是這樣的 alert(null && Object);//將返回null,因為在AND運算中第一條件為false,就無須繼續了 //同理,OR運算也是如此 alert(Object || String);//返回Object,因為它的邏輯值是true alert(false || NaN);//返回NaN
數學運算子
加法(+),減法(-),乘法(*),除法(/)以及取模(%)都是小學數學的內容了,這裡我們主要討論在ECMAScript中,當這些運算子與一些特殊值相遇時會是什麼情況
- 加法(+)
- -Infinity 加 -Infinity,結果為 -Infinity。Infinity 加 Infinity,結果為 Infinity。
- Infinity 加 -Infinity,結果為 NaN。
- 當只要有一邊是字串時,兩邊都被轉換成字串進行相連
- 減法(-)
- -Infinity 減 Infinity,結果為 NaN。
- -Infinity 減 -Infinity,結果為 NaN。
- Infinity 減 -Infinity,結果為 Infinity。
- -Infinity 減 Infinity,結果為 -Infinity。
- 乘法(*)
- 如果結果太大或太小,那麼生成的結果是 Infinity 或 -Infinity。
- Infinity 乘以 0 以外的任何數字,結果為 Infinity 或 -Infinity。
- Infinity 乘以 Infinity,結果為 Infinity。
- 除法(/)
- 如果結果太大或太小,那麼生成的結果是 Infinity 或 -Infinity。
- Infinity 被 Infinity 除,結果為 NaN。
- Infinity 被任何數字除,結果為 Infinity。
- 0 除一個任何非無窮大的數字,結果為 NaN。
- Infinity 被 0 以外的任何數字除,結果為 Infinity 或 -Infinity。
- 取模(%)
- 如果被除數是 Infinity,或除數是 0,結果為 NaN。
- Infinity 被 Infinity 除,結果為 NaN。
- 如果除數是無窮大的數,結果為被除數。
- 如果被除數為 0,結果為 0。
如果對其它型別的值進行數學運算,那麼其它型別的值會自動轉換成數字,如果轉換失敗,則返回NaN(只有加法運算可以和普通字串相連)
語句
判斷語句:if (condition) {...} , if (condition) {....}else {....} , if (condition) {....} else if (condition) {......} else {.....}
迴圈語句:while (condition) {...} , do {...} while (condition) ,for (initialization; expression; post-loop-expression) statement; for (var key in obj) {......}
有標籤的語句與break,continue語句
break 和 continue 語句的不同之處:break 語句可以立即退出迴圈,阻止再次反覆執行任何程式碼。而 continue 語句只是退出當前迴圈,根據控制表示式還允許繼續進行下一次迴圈。
var iNum = 0; outermost: for (var i=0; i<10; i++) { for (var j=0; j<10; j++) { if (i == 5 && j == 5) { break outermost; } iNum++; } } alert(iNum); //輸出 "55"
with 語句用於設定程式碼在特定物件中的作用域。
var sMessage = "hello"; with(sMessage) { alert(toUpperCase()); //輸出 "HELLO" } var person = new Object(); person.age = 18; person.name = "XXX"; person.parent = "ZZZ"; with (person) { alert(age+"\n"+name+"\n"+parent); }
with 語句是執行緩慢的程式碼塊,尤其是在已設定了屬性值時。大多數情況下,如果可能,最好避免使用它。