隱式類型轉換
使用Boolean(), Number(), String()去轉換數據類型的方法叫顯示類型轉換,而與它相對的就是隱式類型轉換,隱式類型轉換並沒有明顯的標志,而是JS解釋器覺得做這樣一個轉換是合適的,就轉換了,例如一元加,一元減,遞增和遞減,它們可以操作任何數據類型,最后的結果都返回數字,這個是比較好理解的,而加減乘除運算中的類型轉換更加復雜麻煩,也因此可能會出現很多奇怪的現象;
乘性操作符
包括乘法、除法和模運算,模運算就是取余數;
在JS中使用乘性操作符時:
- 如果兩邊的操作數都是數字,那么就進行數學運算;
- 如果有一個操作數不是數字的話,就把這個操作數轉換成數字,例如
1 * '2'; //'2'會被轉換成數字2,然后再參與到運算中
- 如果操作數不能轉換成普通數字,例如
1 * 'abc'; //’abc’會被轉換成NaN(不要忘了NaN其實也是一個數字),然后再進行數學運算,結果是NaN
NaN與任何數進行計算結果都是NaN;
注意問題:
1, 涉及到小數計算的時候一定要注意,0.1 * 0.2不等於0.02,而是一個與0.02非常接近的數字,如果要做精確的計算的話,建議先把小數轉換成整數,再把結果轉回小數;
2, 進行模運算的時候,結果不一定是整數,也可以是小數,如1.5 % 1.2,結果是0.30000000000000004;
3, 使用乘性操作符最后得到的結果一定是一個數字類型;
減法操作符
減法操作符與乘性操作符的規則是相似的:
- 如果兩邊都是數字,那就進行減法操作;
- 如果有一邊不是數字,那么就先把它轉換成數字再做減法運算;
記住NaN和任何數字進行運算都等於NaN,同時使用減法操作符的時候也要注意小數的問題;
加法操作符
加法操作符可以說是開發中用得最多的一個操作符,也是比較復雜的,它的運算規則與乘性操作符和減法操作符不太一樣;
使用加法操作符的情況有兩種:
- 兩個數字相加;
- 兩個字符串拼接;
- 如果兩邊都是數字類型或布爾類型,那就進行簡單的數字相加,或者把布爾類型轉換成數字再相加;
1 + 1; // 2 1 + true; // 2 true + false; // 1
- 如果左右兩個操作數中有一個是字符串,或者兩個都是字符串的時候,那就進行字符串的拼接;
1 + '1'; // "11" '1' + true; // "1true"
如果你不確定操作數的數據類型,那么可以先對它做一個顯式轉換;
String(a) + String(b); // 得到一個字符串 Number(a) + Number(b); // 得到一個數字
關系運算符
- 如果是對兩個數字進行比較操作,那就是簡單的數字比較,返回一個布爾值;
- 如果是對字符串進行比較,這種比較是基於字符編碼的,‘B‘會小於’a‘,因為'B'的編碼比'a'小;
- 如果有對象要參與到關系比較中,首先會把對象轉換成一個原始值再進行比較,轉換過程中會先調用對象的valueOf方法,再調用toString方法;
- 如果有一個操作數是數字,那么會把另外一個操作數轉換成數字;
- 如果有一個操作數是NaN,那么運算結果就是NaN,因為NaN不等於任何數字;
關系運算符的返回結果都是一個布爾值;
關系運算符是二元運算符,所以它的結合性是左結合,也就是從左向右運算,所以可能會出現這樣一個問題
7 > 6 > 5;
這行代碼看上去好像應該返回true,但其實不是,JS會先計算7 > 6,得到true,再計算true > 5,把true轉換成數字之后也就是1 > 5,最后的結果是false;
在加法操作和關系操作中都會進行隱式類型轉換,但不同的是加法操作符更偏向於字符串的處理,而比較運算符則偏向於數字的處理;在加法操作中,如果有一個操作數是字符串,那另一個操作數也會被轉換成字符串,而在比較運算中,如果有一個操作數是數字,那另一個操作數會被轉換成數字;
建議無法確定操作數的數據類型時,先對它們進行顯式數據類型轉換;
=== 全等判斷
- 首先判斷類型是否相同,如果類型不相同直接返回false,只有兩個操作數類型相同的情況下才會進行下一步;
- 如果兩邊都是數字,那就判斷兩個數值是否相等,但是要注意的是,在JS中,NaN不等於NaN,它也是唯一一個與自身不相等的值;
- 如果兩邊都是布爾類型,那就判斷布爾值是否相同;
- 如果兩邊都是字符串,那就判斷兩個字符串的編碼是否相同,所以看上去相等的兩個字符串可能並不相等,因為它們的編碼可能不相同;
- undefined和null只和自身相等,因為這兩個數據類型都只有一個值;
- 如果是兩個對象參加判斷,那么判斷的是對象的引用,所以即使是兩個看起來相同的對象參加判斷的結果也是不相等,因為這可能是兩個獨立的對象,那么引用地址是不一樣的,
== 相等判斷
它與全等的區別就是它會進行一個隱式類型轉換的操作,比如null和undefined,如果對它們進行全等判斷,那么結果會是false,因為它們的類型不一樣,但如果對它們進行相等判斷,結果會是true;
- 當進行數字和字符串的相等判斷時,會把字符串先轉換成數字,然后再進行比較;
- 如果有一個操作數是布爾類型,會先把這個操作數轉換成數字;
true == '1'; // 先把true轉換成1,再按照第一條規則把'1'轉換成1,再進行比較,得到結果true
- 對對象進行相等判斷時,判斷的是引用地址是否是同一個;
當進行對象和原始類型進行相等判斷時,首先會先調用對象的valueOf方法,再調用toString方法,把對象轉換成原始類型,然后再進行比較;但日期對象比較特殊,它會調用toString方法轉換成原始類型;
但日常開發中用得比較多的一個是null和undefined的比較,一個是數字和字符串的比較,會先把字符串轉換成數字;
不全等(!==)和不相等(!=)
與全等和相等是相對的,結果反過來就是了;
= 賦值
賦值操作符其實是一個二元操作符,但不同的是,它左側的表達式必須是一個變量或者是對象的屬性,也就是說,它的左側是一個可以改變的值,也被成為左值;賦值操作符右側的表達式可以是任何數據類型;
var num = 10; num = num + 10;
在這行代碼中,首先會進行加法操作,再進行賦值操作,這是因為賦值操作符的優先級比加法操作符低;注意代碼不要寫成num + 10;因為 這樣只是進行了計算,沒有保存結果,不要把它和num++;搞混,num++;與num = num + 1;的結果是一致的;
復合賦值操作符
也就是帶操作符的賦值操作,在等號(=)前面再寫一個運算符,一般是
+=
-=
*=
/=
%=
這只是在寫法上簡單一點,但是性能上完全沒有提升;
連續賦值
var a = b = 1;
不推薦這樣寫,這樣b成了全局變量,造成變量污染;
如果a和b是兩個對象,尤其是兩個有關聯的對象,問題會更復雜;
————整理自沙翼老師的前端音頻教程#陪你讀書#(喜馬拉雅)