【讀書筆記】JavaScript高級編程(三)

書中第3章 基本概念摘要(二) 編程

3.5 操做符

3.5.1 一元操做符

1.遞增和遞減操做符
var s1 = "2";
var s2 = "z";
var b = false;
var f = 1.1;
var o = {
    valueOf: function() {
        return -1;
    }
};

s1++; // 值變成數值3
s2++; // 值變成NaN
b++; // 值變成數值1
f--; // 值變成0.10000000000000009(因爲浮點舍入錯誤所致)
o--; // 值變成數值-2
4個操做符(a++,++a,a--,--a)對任何值都適用,在應用於不一樣的值時,遞減和遞增操做符遵循下列規則。
    應用於一個包含有效數字字符的字符串時,先將其轉換爲數字值,再執行加減1的操做。字符串變量變
成數值變量。
    在應用於一個不包含有效數字字符的字符串時,將變量的值設置爲 NaN 。字符串變量變成數值變量。
    在應用於布爾值false時,先將其轉換爲0再執行加減1的操做。布爾值變量變成數值變量。
    在應用於布爾值true時,先將其轉換爲1再執行加減1的操做。布爾值變量變成數值變量。
    在應用於浮點數值時,執行加減1的操做。
    在應用於對象時,先調用對象的valueOf()方法以取得一個可供操做的值。而後對該值應用前述規則。
若是結果是NaN,則在調用toString()方法後再應用前述規則。對象變量變成數值變量。

2.一元加和減操做符
var s1 = "01";
var s2 = "1.1";
var s3 = "z";
var b = false;
var f = 1.1;
var o = {
    valueOf: function() {
        return -1;
    }
};
s1 = +s1; // 值變成數值1
s2 = +s2; // 值變成數值1.1
s3 = +s3; // 值變成NaN
b = +b; // 值變成數值0
f = +f; // 值未變,仍然是1.1
o = +o; // 值變成數值-1

var s1 = "01";
var s2 = "1.1";
var s3 = "z";
var b = false;
var f = 1.1;
var o = {
    valueOf: function() {
        return -1;
    }
};
s1 = -s1; // 值變成數值-1
s2 = -s2; // 值變成數值-1.1
s3 = -s3; // 值變成NaN
b = -b; // 值變成數值0
f = -f; // 值變成-1.1
o = -o; // 值變成數值1

3.5.3 布爾操做符

1.邏輯非
alert(!false); // true
alert(!"blue"); // false
alert(!0); // true
alert(!NaN); // true
alert(!"");  // true
alert(!" "); // false
alert(!12345); // false
邏輯非操做符會將它的操做數轉換爲一個布爾值,而後在對其求反。
    若是操做數是一個對象,返回false;
    若是操做數是一個空字符串,返回true;
    若是操做數是一個非空字符串,返回false;
    若是操做數是數值0,返回true;
    若是操做數是任意非0數值(包括Infinity),返回false;
    若是操做數是操做數是null,返回true;
    若是操做數是NaN,返回true;
    若是操做數是undefined,返回true。

2.邏輯與
邏輯與操做能夠應用於任何類型的操做數,而不只僅是布爾值。在有一個操做數不是布爾值的狀況下,邏輯
與操做就不必定返回布爾值;此時,它遵循下列規則:
    若是第一個操做數是對象,則返回第二個操做數;
    若是第二個操做數是對象,則只有在第一個操做數的求值結果爲true的狀況下才會返回該對象;
    若是兩個操做數都是對象,則返回第二個操做數;
    若是有一個操做數null,則返回null;
    若是有一個操做數是NaN,則返回NaN;
    若是有一個操做數是undefined,則返回undefined。

短路操做:
    var found = true;
    var result = (found && someUndefinedVariable); // 這裏會發生錯誤
    alert(result);  //這一行不會執行
上面代碼中,由於found爲true,因此邏輯與操做符會繼續對變量someUndefinedVariable求值。但
someUndefinedVariable還沒有定義,所以就會致使錯誤。這說明不能在邏輯與操做中使用未定義的值。若是將found的值設爲false,發生「短路」不會對someUndefinedVariable繼續求值,就不會發生錯誤:
    var found = false;
    var result = (found && someUndefinedVariable); // 不會發生錯誤
    alert(result);  //會執行alert

3.邏輯或
與邏輯與操做類似,若是有一個操做數不是布爾值,邏輯或也不必定返回布爾值;此時,它遵循下列規則:
    若是第一個操做數是對象,則返回第一個操做數;
    若是第一個操做數的求值結果爲false,則返回第二個操做數;
    若是兩個操做數都是對象,則返回第一個操做數;
    若是有一個操做數null,則返回null;
    若是有一個操做數是NaN,則返回NaN;
    若是有一個操做數是undefined,則返回undefined。

短路操做:
    var found = true;
    var result = (found || someUndefinedVariable); // 不會發生錯誤
    alert(result);  // 會執行alert
這個例子跟前面例子同樣,變量someUndefinedVariable也沒有定義。可是,因爲變量found的值是true,而
變量someUndefinedVariable永遠不會被求值,所以不會報錯。
    var found = false;
    var result = (found || someUndefinedVariable); // 這裏會發生錯誤
    alert(result);  // 這一行不會執行
咱們能夠利用邏輯或的這一行爲來避免爲變量賦null或undefined值。例如:
    var myObject = preferredObject || backupObject;
在這個例子中,變量myObject將被賦予等號後面兩個值中的一個。變量preferredObject中包含優先賦給變
量myObject的值,變量backupObject負責在preferredObject中不包含有效值的狀況下提供後備值。

3.5.4 乘性操做符
ECMAScript定義了3個乘性操做符:乘法、除法和求模。這些操做符與Java、C或者Perl中的相應操做符相似
,只不過在操做數爲非數值的狀況下會執行自動的類型轉換。若是參與乘法計算的某個操做數不是數值,後臺會先使用Number()轉型函數將其轉換爲數值。也就是說,空字符串將被看成0,布爾值true將被看成1。

1.乘法
在處理特殊值的狀況下,乘法操做符遵循下列特殊的規則:
    若是操做數都是數值,執行常規乘法計算。若是乘積超過了ECMAScript數值的表示範圍,則返回
Infinity或-Infinity;
    若是有一個操做數是NaN,則結果是NaN;
    若是是Infinity與0相乘,則結果是NaN;
    若是是Infinity與非0數值相乘,則結果是Infinity或-Infinity,取決於有符號操做數的符號;
    若是是Infinity與Infinity相乘,則結果是Infinity;
    若是有一個操做數不是數值,則在後臺調用Number()將其轉換爲數值,而後再應用上面的規則。

2.除法
與乘法相似,對特殊值的處理規則以下:
    若是操做數都是數值,執行常規除法計算。若是乘積超過了ECMAScript數值的表示範圍,則返回
Infinity或-Infinity;
    若是有一個操做數是NaN,則結果是NaN;
    若是是Infinity被Infinity除,則結果是NaN;
    若是是Infinity被任意數值除,則結果是Infinity;
    若是是零被零除,則結果是NaN;
    若是是非零的有限數被零除,則結果是Infinity或-Infinity,取決於有符號操做數的符號;
    若是是Infinity被任何非零數值除,則結果是Infinity或-Infinity,取決於有符號操做數的符號;
    若是有一個操做數不是數值,則在後臺調用Number()將其轉換爲數值,而後再應用上面的規則。

3.求模
var result = 26 % 5; //等於1
與另外兩個乘法操做符相似,求模操做符會遵循下列特殊規則來處理特殊的值:
    若是操做數都是數值,執行常規除法計算。返回除得的餘數;
    若是被除數是無窮大值而除數是有限大的數值,則結果是NaN;
    若是被除數是有限大的數值而除數是零,則結果是NaN;
    若是是Infinity被Infinity除,則結果是NaN;
    若是被除數是有限大的數值而除數是無窮大的數值,則結果是被除數;
    若是被除數是零,則結果是零;
    若是有一個操做數不是數值,則在後臺調用Number()將其轉換爲數值,而後再應用上面的規則。

3.5.5 加性操做符

1.加法
若是兩個操做數都是數值,執行常規的加法計算,而後根據下列規則返回結果:
    若是有一個操做數是NaN,則結果是NaN;
    若是是Infinity加Infinity,則結果是Infinity;
    若是是-Infinity加-Infinity,則結果是-Infinity;
    若是是Infinity加-Infinity,則結果是NaN;
    若是是+0加+0,則結果是+0;
    若是是-0加-0,則結果是-0;
    若是是+0加-0,則結果是+0;
不過,若是有一個操做數是字符串,那麼就要應用以下規則:
    若是兩個操做數都是字符串,則將第二個操做數與第一個操做數拼接起來;
    若是隻有一個操做數是字符串,則將另外一個操做數轉換爲字符串,而後再將兩個字符串拼接起來。
若是有一個操做數是對象、數值或布爾值,則調用它們的toString()方法取得相應的字符串值,而後再應用
前面關於字符串的規則。對於undefined和null,則分別調用String()函數並取得字符串"undefined"和"null"。
    var result1 = 5 + 5;  //兩個數值相加
    alert(result1);  //10
    var result2 = 5 + "5";  //一個數值和一個字符串相加
    alert(result2);  //"55"
忽視加法操做中的數據類型是ECMAScript編程中最多見的一個錯誤,以下
    var num1 = 5;
    var num2 = 10;
    var message = "The sum of 5 and 10 is " + num1 + num2;
    alert(message);  // "The sum of 5 and 10 is 510"
若是想先對數值執行計算,而後再拼接,應該像下面這樣使用圓括號:
    var num1 = 5;
    var num2 = 10;
    var message = "The sum of 5 and 10 is " + (num1 + num2);
    alert(message);  // "The sum of 5 and 10 is 15"


2.減法
與加法相似,減法操做符在處理各類數據類型轉換時,一樣須要遵循一些特殊規則:
    若是兩個操做數都是數值,執行常規的減法運算並返回結果:
    若是有一個操做數是NaN,則結果是NaN;
    若是是Infinity減Infinity,則結果是NaN;
    若是是-Infinity減-Infinity,則結果是NaN
    若是是Infinity減-Infinity,則結果是Infinity;
    若是是-Infinity減Infinity,則結果是-Infinity;
    若是是+0加+0,則結果是+0;
    若是是-0加-0,則結果是+0;
    若是是+0加-0,則結果是-0; 
    若是有一個操做數是字符串、布爾值、null或undefined,則先在後臺調用Number()函數將其轉換爲數
值,而後再根據前面的規則執行減法計算。若是轉換的結果是NaN,則減法的結果就是NaN;
    若是有一個操做數是對象,則調用對象的valueOf()方法以取得表示該對象的數值。若是獲得的值是NaN,則減法的結果就是NaN。若是對象沒有valueOf()方法,則調用其toString()方法並將獲得的字符串轉換爲數值。   
var result1 = 5 - true; // 4,由於true被轉換成了1
var result2 = NaN - 1; //NaN
var result3 = 5 - 3; // 2
var result2 = 5 - ""; //5, 由於""被轉換成了0
var result2 = 5 - "2"; //3,由於"2"被轉換成了2
var result2 = 5 - null; //5,由於null被轉換成了0

3.5.6 關係操做符
小於(<)、大於(>)、小於等於(<=)和大於等於(>=)這幾個關係操做符用於對兩個值進行比較,比較的規則與
咱們在數學課上所學的同樣,這幾個操做都返回一個布爾值。當關系操做符的操做數使用了非數值時,也要進行數據轉換或完成某些奇怪的操做。
    若是兩個操做數都是數值,則執行數值比較;
    若是兩個操做數都是字符串,則比較兩個字符串對應的字符編碼值;
    若是一個操做數是數值,則將另外一個操做數轉換爲一個數值,而後執行數值比較;
    若是一個操做數是對象,則調用這個對象的valueOf()方法,用獲得的結果按照前面的規則執行比較。
若是對象沒有valueOf()方法,則調用toString()方法,並用獲得的結果根據前面的規則執行比較;
    若是一個操做數是布爾值,則先將其轉換爲數值,而後再執行比較。

在比較字符串時,實際比較的是兩個字符串中對應位置的每一個字符的字符編碼值。通過一番比較以後,再返
回一個布爾值。因爲大寫字母的字符編碼所有小於小寫字母的字符編碼,所以咱們就會看到以下所示的奇怪現象:
    var result = "Brick" < "alphabet";  //true
在這個例子中,字母B的字符編碼爲66,而字母a的字符編碼是97.若是想按照字母表順序比較字符串,就必
須把兩個操做數轉換爲相同的大小寫形式(所有大寫或所有小寫),而後再執行比較:
    var result = "Brick".toLowerCase() < "alphabet".toLowerCase();  //false
另外一種奇怪的現象發生在比較兩個數字字符串的狀況下,好比:
    var result = "23" < "3";  //true
這是由於兩個操做符數都是字符串,而字符串比較的是字符編碼("2"的字符編碼是50,而"3"的字符編碼是
51)。不過,若是將一個操做數改成數值,比較的結果就正常了:
    var result = "23" < 2;  //false
若是字符串爲一個不能被轉換成合理的數值的字符呢?
    var result = "a" < "3";  //false,由於"a"被轉換成了NaN。
任何操做數與NaN進行關係比較,結果都是false。
    var result1 = NaN < 3;  //false
    var result2 = NaN >= 3;  //false

函數

3.5.7 相等操做符 編碼

1.相等和不相等
相等操做符 == ,不相等操做符 != 。這兩個操做符都會先轉換操做數(一般稱爲強制轉型),而後再比較它們的相等性。
spa

在轉換不一樣數據類型時,相等和不相等操做符遵循下列基本規則:
    若是有一個操做數是布爾值,則在比較相等性以前先將其轉換爲數值——false轉換爲0,而true轉換爲1;
    若是一個操做數是字符串,另外一個操做數是數值,在比較相等性以前先將字符串轉換爲數值;
    若是一個操做數是對象,另外一個操做數不是,則調用對象的valueOf()方法,用獲得的原始值按照前面的規則進行比較;
這兩個操做符在進行比較時則要遵循下列規則。
    null和undefined是相等的。
    要比較相等性以前,不能講null和undefined轉換成其餘任何值。
    若是有一個操做數是NaN,則相等操做符返回false,而不相等操做符返回true。重要提示:即便兩個操做數都是NaN,相等操做符也返回false;所以按照規則,NaN不等於NaN。
    若是兩個操做數都是對象,則比較它們是否是同一個對象。若是兩個操做數都指向同一個對象,則相等操做符返回true;不然,返回false。
下表列出了一些特殊狀況及比較結果:

設計

2.全等和不全等 對象

除了在比較以前不轉換操做數以外,全等和不全等操做符與相等和不相等操做符沒有什麼區別。全等操做符 === 
    var result1 = ("55" == 55);  //true,由於轉換後相等
    var result2 = ("55" === 55);  //false,由於不一樣的數據類型不相等
不全等操做符 !==
    var result1 = ("55" != 55);  //false,由於轉換後相等
    var result2 = ("55" !== 55);  //true,由於不一樣的數據類型不相等
ip

3.5.8 條件操做符 字符串

條件操做符遵循與Java中的條件操做符相同的語法形式。 數學

3.5.10 逗號操做符 it

使用逗號操做符能夠在一條語句中執行多個操做,以下:
    var num1=1, num2=2, num3=3;
 逗號操做符多用於聲明多個變量;但除此以外,逗號操做符還能夠用於賦值。在用於賦值時,逗號操做符總會返回表達式中的最後一項,以下:
    var num = (5, 1, 4, 8, 0); //num值爲0

以上全部內容均摘自圖書《JavaScript 高級程序設計(第2版)》[美] Nicholas C.Zakas 著 李鬆峯 曹力 譯

相關文章
相關標籤/搜索