學習 JavaScript (四)核心概念:操作符
JavaScript 的核心概念主要由語法、變數、資料型別、操作符、語句、函式組成,前面三個上一篇文章已經講解完了。後面三個內容超級多,這篇文章主要講解的是操作符。
操作符
什麼叫做操作符?
這是一種工具,幫助我們操作字串、數字值、布林值,乃至物件,運用一些操作符能夠讓程式碼更簡潔、計算更高效。它包括以下幾種:
- 賦值操作符
- 一元操作符(加、減)
- 位操作符
- 關係操作符
- 相等操作符
01 賦值操作符
賦值操作符就是我們常見的 “=”,作用就是把右邊的值賦給左邊的變數。比如:
let a = 1;
如果複雜一些(效能上不會有提升,看起來牛*一點而已),就是結合後面要碰到的操作符,變成這樣:
*= ; // 乘/賦值 // 舉例 let num = 10; num = num * 10; // 和下面的用法效果一樣 num *= 10; 下面的複雜賦值操作符如下: /= ; // 除/賦值 %= ; // 模/賦值 += ; // 加/賦值 -= ; // 減賦值 <<= ; // 左移賦值; >>=; // 有符號右移; >>>= ; // 無符號右移;
02 一元操作符
記住:只對一個數值進行操作的符號叫做一元操作符,而不是指操作符自身的數量。
遞增操作:兩個加號 ++
前置操作 ++i ,i 先自己加上 1 ,然後拿著計算後的 i 值進行下一步計算。
let i = 1;
let result = ++i + 20
console.log(i) // 2
console.log(result) // 22
後置操作 i++,先進行下一步計算,然後再自己加上1。
let i = 1;
let result = i++ + 20
console.log(i) // 2
console.log(result) // 21
遞減操作:兩個加號 --
遞減操作和遞增操作的規則一樣,-- 符號在前面就先進行遞減操作,否則就等接下來的計算進行完再遞減。
前置操作 --i ,i 先自己減去 1 ,然後拿著計算後的 i 值進行下一步計算。
let i = 1;
let result = --i + 20
console.log(i) // 0
console.log(result) // 20
後置操作 i--,先進行下一步計算,然後再自己減去1。
let i = 1;
let result = --i + 20
console.log(i) // 0
console.log(result) // 21
統一記憶成:符號在前,馬上加減。
加和減操作符
前面講的是兩個相同的符號聯合起來操作一個數值,而家下來介紹的這個操作符只有一個。
+
或者 -
,對於數值來說,+
沒有任何作用,對於 -
如果我們把操作符用在其他資料型別上,會發生怎樣的情況呢?直接看例子:
let a = "01";
a = +a; // 1
let b = "1.1";
b = +b; // 1.1
let c = "z";
c = "z"; // NaN
let d = "true";
d = "true"; // 1
let e = 1.1;
e = 1.1; // 1.1
let o = {
valueOf: function(){
return -1;
}
} // 如果沒有看懂這個物件的寫法,不用著急,後面會針對物件做進一步的解釋。
o = +o ; -1
而 -
操作則是在+
操作的結果前面加上負號(-)而已。其他型別的資料的轉換規則依然不變。
03 位操作符
位操作符是在最基本的、最底層的水平上對數值進行操作,也就是在記憶體中直接對二進位制進行操作。
JavaScript 中的所有資料都是按照 64 位儲存的,但是位操作符並不能直接對 64 位的資料進行操作,而是將其轉換成 32 位的,操作完成後,再轉換成 64 位的,所以我們真正關心的是計算機如何操作 32 位的數值。
對於有符號的整數,二進位制從右往左數,32 位中的前 31 位表示整數的值,第 32 位是符號位,表示數值的符號,0 表示正數,1 表示負數。比如 數值 18 表示成二進位制為:
0 0000000000000000000000000010010
符號位
寫成簡潔版的:
10010
31 位中每一位都表示 2 的冪,所以從二進位制轉換成數值:
(2^4 x 1) + (2^3 x 0) + (2^2 x 0) + (2^1 x 1) + (2^0 x 0) = 18
這是正數的二進位制表達方式,負數的二進位制需要用到二進位制補碼。步驟如下:
- 求這個數值的絕對值的二進位制;
- 求二進位制反碼,將 0 替換成 1,將 1 替換成 0 ;
- 得到的二進位制反碼加 1 ;
舉一個例子(-18):
-18 的絕對值等於 18:
0 0000000000000000000000000010010
求二進位制反碼:
1 1111111111111111111111111101101
反碼加 1
1 1111111111111111111111111101110
最終得到的結果就是 11111111111111111111111111101110 。但是計算機給我們看的結果卻不是這樣,把 -18 轉換成字串會發現得到的結果是“-10010”,計算機隱藏了計算過程,直接展示友好的結果而已,別被騙了。
因為是底層操作,所以應用位操作的計算方式會比普通計算方式要快:
- 按位非(NOT)
- 符號:~ ;
- 作用物件:一個數值(數字、字串、布林值、物件);
- 操作:把運算元變成相反數再減去一 ;
- 例子:
~2 == -3
、~-2 == 1
、~true == -2
。
- 按位與(AND)
- 符號:& ;
- 作用物件:兩個數值;
- 操作:將兩個數值的二進位制形式中的每一位對齊,然後依據普通的與操作進行合併,把 1 看成 true,把 0 看成 false , 即 1 和 1 組合是 1 ,1 和 0 組合是 0 , 0 和 0 組合是 0 。得到的二進位制再轉換成 十進位制就可以了;
- 例子:
25 & 3 == 1
;
- 按位或(OR)
- 符號:| ;
- 作用物件:兩個數值;
- 操作:和按位與的操作類似,與之不同的是,按位或操作時,只要碰到 1 就返回 1 ,只有兩個對應的位全部為 0 時才返回 0 ;
- 例子:
25 | 3 == 27
。
- 按位異或(XOR)
- 符號:^ ;
- 作用物件:兩個數值;
- 操作:有且僅有一個位是 1 ,另一個位是 0 ,才返回 1 ,否則都返回 0,即 1 和 1 也返回 0;
- 例子:
25 ^ 3 == 26
。
- 左移
- 符號:<< ;
- 作用物件:一個數值;
- 操作:將數值的所有位向左移動指定的位數,右側多出來的空位由 0 進行填充;
- 例子:
2 << 5 == 64
,2 向左移動 5 位,左移不會影響運算元的符號位,即 -2 ; ,左移後的結果將會是 -64。
- 右移
- 符號:>> ;
- 作用物件:一個數值;
- 操作:將數值的所有位向右移動指定的位數,符號位不動,左側多出來的空位由 0 進行填充;
- 例子:
64 >> 5 == 2
,64 向右移動 5 位,右移不會影響運算元的符號位,即 -64 ,右移後的結果將會是 -2。
- 無符號右移
- 符號:>>>;
- 作用物件:一個數值;
- 操作:將數值的所有位向右移動指定的位數,左側多出來的空位由 0 進行填充,這個時候符號位也要向右移動。可以知道,對於正數而言,這個操作和右移是一樣的結果,但是對於負數來說,因為符號位是 1 ,移動後要計入最終結果;
- 例子:
-64 >>> 5 == 134217726
。
04 布林操作符
在上述位操作符中的按位非、按位與、按位或,我們已經簡單介紹了一些跟布林操作類似的用法。
總的來說,布林操作的地位跟相等操作符(==、===)的地位是一樣的,一共右三種:非(NOT)、與(AND)、或(OR)。
- 邏輯非
- 符號:!;
- 作用物件:一個數值;
- 操作:先將數值轉換成一個布林值,再取反;
- 例子:
要點:此時連用兩個 “!”,則跟布林轉換函式 Boolean() 的作用是一樣的,即還原了數值本身代表的布林值。!false; //true !true; //false !null; //true !{}; // false !0; //true !123; //false !""; //true !"abc"; //false
- 邏輯與
- 符號:&&;
- 作用物件:兩個數值;
- 操作:比較兩個數值的布林值,返回結果(不一定是布林值);
- 例子:
true && true; //true true && false; //false false && true; // fasle false && false; // false
要點:
- 這裡的 true 和 false,可以替換成別的數值型別,比如物件、null等
- 邏輯與是短路操作,只要第一個運算元或者運算元的轉換值是 false ,計算終止,直接返回 false 。如果是 true 的話再返回後面的值。
- 在寫判斷語句的時候經常會用到。
- 邏輯或
- 符號:||;
- 作用物件:兩個數值;
- 操作:比較兩個數值的布林值,返回結果(不一定是布林值);
- 例子:
true || true; //true true || false; //true false || true; // true false || false; // false
要點:
- 邏輯或也是短路操作,只要第一個運算元或者運算元的轉換值是 true ,計算終止,直接返回第一個運算元。如果是 false 的話,返回第二個運算元。
- 利用邏輯或的性質,我們在定義變數的時候可以給它找個備胎,降低 Bug 發生率。
04 乘性操作符
乘性操作符包括三種:乘法、除法、求模。在 JavaScript 中,運算元為非數值的情況下也能計算。比如:
"10" * 2 ; // 計算結果為 20
可以看得出來,計算機自動執行了型別轉換,如果參與的運算元不是數值,會先用 Number() 函式轉換。
- 乘法:
- 符號: *
- 舉例:
4 * 5
有三點需要注意:
- 乘積超過 JavaScript 範圍,用 Infinity表示無窮大 或者 -Infinity 表示負無窮大;
- Infinity 和 0 相乘是 NaN;
其中一個運算元是 NaN,則結果是 NaN。因為 Number() 轉換非數值型字串是 NaN,所以非數值型字串和數字相乘就是 NaN 。其他的規則與乘法操作符類似。
- 除法:
- 符號: /
- 舉例:
44 / 11 ;等於 4
有一點需要注意:如果 Infinity 被 -Infinity 除,那麼結果是 NaN。 ---
- 求模:
- 符號: %
- 舉例:
26 % 5 ;等於 1
求模就是取餘數。
05 加性操作符
加法和減法都被稱作是加法操作符。在這裡說明一下,加性操作符也會強制轉換資料型別。
- 加法:
- 符號: +
- 舉例:
1 + 1
需要注意的是,
- 如果兩個運算元都是字串,那麼直接拼接起來返回結果;如果其中一個運算元是字串,那麼就把另一個運算元轉換乘字串再拼接起來。
- 利用 Chrome 的 console 命令視窗,實驗得到如下的規則:
{} + 11; // 11
11 + {}; // "11[object,object]"
false + 1; // 1 ; 運算元可以調換位置,結果不變
true + 1; // 2 ; 同上
null + 1;// 1 ;同上
undefined + 1 ; // NaN;同上
- 減法:
- 符號: -
- 舉例:
2 - 1
減法兩邊的運算元和加法的區別是,無論是字串還是物件,都應該轉換成數值,再進行計算。不存在字串相減的情況。
06 關係操作符
關係操作符就是小學的時候學過的小於(<)、大於(>)、小於或等於(<=)、大於或等於(>=)。
JavaScript 中,使用關係操作符比較兩個運算元後,返回的結果是布林值(true、false)。
需要注意的是,
當比較的兩個數都是數值時,直接比數字大小;
如果都是字串則比較對應位置的字元編碼值。比如:
"Brick" < "apple"; //返回的是 true,因為 B 的字元編碼是 66 ,而 a 的字元編碼是 97 "23" < "3"; // 返回 true,因為 2 的字元編碼是 50 ,3 的字元編碼是 51 。
- 如果其中一個是數字,則把另一個運算元變為數值以後再比較;
任何資料型別和 NaN 比較都是返回 false。
這裡有個小思考:如果 A、B 表示兩個資料,有 A > B 不成立(false),則 A <= B 是否成立?
07 相等操作符
JavaScript 提供兩種比較方案:
相等(
==
)和不相等(!=
),會把運算元轉換成相似的型別再比較。"5" == 5; //true
- null 和 undefined 是相等的;
- 如果有一個運算元是 NaN 則返回 false ;
- NaN 和 NaN 不相等,NaN 返回 true ;
嚴格相等(
===
)和嚴格不相等(!==
),直接比較,不轉換資料型別,使用嚴格相等操作符,有一丁點不相等就返回 false。"5" === 5; //false
- null 和 undefined 是不嚴格相等的
總之,在實際使用過程種,建議是使用嚴格相等和嚴格不相等。
08 條件操作符
條件操作符也被稱作是三目運算子,用法如下:
let a = 條件語句 ? 1 :2
如果條件語句返回的是 true ,則把 1 賦值給 a,如果是 false, 則把 2 賦值給 a。
返回一個較大值,我們就可以不用謝一個 if 語句,直接按照下面這種寫法就可以實現:
let a = (number1 > number2) ? number1 : number2
歡迎大家關注微信公眾號:視覺化技術( visteacher )
不僅有前端和視覺化,還有演算法、原始碼分析、書籍相送
各個分享平臺的 KurryLuo 都是在下。
用心學習,認真生活,努力工作!