# Javascript 第三章 運算元和運算子 ###### tags: `JS X Codeshiba` ## 運算式(Expression)和運算子(Operator)\ JS的語法可以分成兩種 1. 敘述句(Statement) **執行某個動作** 變數宣告、賦值或是if判斷式都是 可以當成一種指令,要求某個東西 ```javascript= var f; ``` 2. 運算式(Expression) **產生一個值** 呼叫function的參數,或是在=的右側,都是屬於運算式的部分 明確地將某個東西轉換成產品 ```javascript= var f = 10*10*10; ``` ## 解構運算式 ```javascript= let x; x=3*5; ``` 第一行是宣告陳述式,宣告變數x 第二行是兩個算數式的結合 1. 乘法運算式: 3*5(常值運算式) 2. 賦值運算式: x=15(識別碼運算式) ## 甚麼是運算子 運算子,類似運算式中的 **「動詞」** ## 運算子的分類 1. 算數運算子(Arithmetic Operator) 2. 指派運算子(Assignment Operator) 3. 位元運算子(Bitwise Operator) 4. 比較運算子(Comparison Operator) 5. 邏輯運算子(Logical Operator) 6. 字串運算子(String Operator) 7. 特殊運算子(Special Operator) ## 算數運算子 1. ++x 預先遞增,表示把x遞增1,接著用新值計算 2. x++ 延後遞增,表示把x遞增1,接著用原先的x來計算 下列的呈現方式都是a=a+1的撰寫方法,不過呈現出來的效果不一樣 a++ 會呈現的是原始的數值 ++a 會呈現的是+1後的數值 ### 算是運算子的特性 1. Infinity 當兩個Infinity相減時(或是加上-Infinity),會產生NaN ![](https://i.imgur.com/5jUgRIq.png) 2. '+'號的使用 自動轉型的特性,讓數字可以和字串相加 如果要規避數字被判斷成字串,可以使用()來處理 ![](https://i.imgur.com/2PPe5vt.png) `+`為運算子(或稱運算符) `數字`為運算元 ![](https://i.imgur.com/uCkMgl0.png) 運算元和運算子可以拿來撰寫條件 ![](https://i.imgur.com/GA3OQKD.png) ### 餘數 ![](https://i.imgur.com/phiK5sq.png) ### 預設值 透過 `||=` 來給予變數預設值 若本身已經被賦予值,則會以原有的值為主 ![](https://i.imgur.com/YmnbNIA.png) ## 比較運算子 ### == 和 === 的比較 如果是要嚴謹的比較,使用`===`,因為這個不會做「自動轉型」 如果比較包含轉換後的型別,則可以使用`==`,但基於上述原因,還是鼓勵使用=== ![](https://i.imgur.com/u1S5P2r.png) 建議可以把字串轉換成數字,改用嚴格相等運算子來比較 ### !=和!==的比較 不等於的意思~~ `!=` 也會把型別自動轉換 `!==` 則不會,所以如果要互相比較,還是使用!==比較好 ### 怎麼對數字進行相等(identity)或一致(equality)的比較 ```javascript= let n = 0; while(true) { n += 0.1; if(n === 0.3) break; } console.log(`stopped at ${n}`); ``` 上述例子無法跳出迴圈,因為數字的特性(都是double),所以無法跳出迴圈,此時可以透過`Number.EPSILON`來改寫迴圈 ```javascript= let n = 0; while(true) { n += 0.1; if(Math.abs(n-0.3)<Number.EPSILON) break; } console.log(`stopped at ${n}`); ``` ### 字串串接的特性 如果使用+號,把200(數字)加上'123'(字串),數字將會自動轉換為字串 如果使用-號,把200(數字)扣掉'123'(字串),文字將會自動轉換為數字 如下所示 ![](https://i.imgur.com/kCFprkC.png) ```javascript= 3+5+"8" //字串88 "3"+5+8 //計算成字串358 ``` ## 邏輯運算子 JS把下列值分為truthy和falsy值 ### truthy 1. 所有物件(包含使用valueOf()方法時,會回傳false的物件) 2. 所有陣列(甚至包括空的陣列) 3. 裡面只有空白的字串(例如" ") 4. 字串"false" ### falsy 1. undefined 2. null 3. false 4. 0 5. NaN 6. ''(空字串) ### And(&&) Or(||) ![](https://i.imgur.com/WFBVRqX.png) AND只會在兩個運算元都是true才會是true OR只會在兩個運算元都是false才會是false ### 短路計算(short-circuit evaluation) and 和 or 也可以透過運算式來比較 值得一提的是,如果只可以透過前面的部分就判定True或False 則電腦只會跑到前面判定的部分為止 例如下方的&&和||跑出來的結果就有所差異 ![](https://i.imgur.com/bgseYAC.png) ### Not(!) ![](https://i.imgur.com/OkqVh9f.png) ### 條件運算子(三源運算子) ```javascript= const doIt = false; const result = doIt ? "Did it!" : "Didn't do it."; //如果doIt是truthy, 則計算Did it //如果doIt是falsy, 則計算Didn't do it ``` ### 逗號運算子 當你想要執行多個運算式,但只關心最後一個運算式的結果時,可以透過以下的範例進行 因為逗號運算子的優先順序偏低,所以我們如果不放在括號內,只會回傳第一個值(x=0) ```javascript= let x = 0, y = 10, z; z = (x++, y++); //z=10; z = x++, y++; //z=0; ``` ## 分組運算子 使用括號,可以修改或明確標示運算子的優先順序 ### typeof運算子 哀,這個運算子無法完全對應JS七種資料型態,所以容易被混淆 | 運算式 | 回傳值 | Memo | |-------|:-----:|------:| | typeof undefined | "undefined" | | | typeof null | "object" | | | typeof {} | "object" | 特別注意 | | typeof true | "boolean" | | | typeof 1 | "number" | | | typeof "" | "string" | | | typeof Symbol() | "symbol" | | | typeof function(){} | "function" | | | typeof [] | "object" | 特別注意 | ### Void運算子 強制執行運算式求值,再回傳undefined 在HTML標籤內的URL可以看得到 ```htmlembedded= <a href="javascript:void 0">Do nothing.</a> ``` ### 賦值運算子 指派一個值給一個變數,在等號左邊的東西是**變數**、**特性**或是**陣列元素**,必須是某種可以保存值的東西 賦值本身是個運算式,所以被回傳的值,就是要指派的值,所以可以把賦值式串起來,在其他運算式中進行賦值 ```javascript= let v, v0; v=v0=9.8; //串接賦值,v0會先得到9.8 //接著v值得到9.8 ``` ```javascript= const nums = [3,5,15,7,5]; let n, i=0; while((n=nums[i])<10, i++ < nums.length){ console.log(`Number less than 10: ${n}.`); } console.log(`Number greater than 10 found: ${n}.`); console.log(`${nums.length} numbers remain.`); ``` ## 解構賦值 ES6內部的功能,可以將一個物件或陣列解構成各個變數 ```javascript= //一般物件 const obj = {b:2, c:3, d:4}; ``` ```javascript= //物件解構賦值 const {a, b, c} = obj; a; // undefined b; // 2 c; // 3 d; // 參考錯誤,未定義"d" ``` 解構物件時,變數名稱必須符合物件中的特性名稱 陣列解構只能指派**識別碼**特性名稱 ```javascript= //我們可以在同一個陳述式中進行宣告與賦值,並在賦值時做物件解構 const obj = {b:2, c:3, d:4}; let a, b, c; {a,b,c} = obj; //這個會產生錯誤 ({a,b,c}=obj); //可以進行解構,但要用括號包起來 //{b: 2, c: 3, d: 4} ``` 使用陣列解構,可以指派任何我想要的名稱 ```javascript= const arr = [1, 2, 'z'] let [x , y] = arr; console.log(x); //1 console.log(y); //2 console.log(f); //錯誤,f沒有被定義 ``` ```javascript= const arr = [1, 2, 'z', 6, 7, 8] let [x , y, ...rest] = arr; //使用擴張運算子(...)來把其餘元素放入新陣列 console.log(x); //1 console.log(y); //2 console.log(rest); //["z", 6, 7, 8] ``` ## 樣板字串中的運算式 ```javascript= const roomTempC = 21.5; let currentTempC = 19.5; const message = `The current temperature is ` + `${currentTempC-roomTempC}\u00b0c different than room temperature.`; const fahrenheit = `The current temperature is ${currentTempC*9/5+32}\u00b0F`; //The current temperature is -2°c different than room temperature. //The current temperature is 67.1°F ``` ## 運算式與控制流程模式 ### 把if...else轉成條件運算式 原有的控制流程: ```javascript= if(isPrime(n)){ label = 'prime'; } else { label = 'non-prime'; } ``` 可以轉換成: ```javascript= label = isPrime(n)? 'prime' : 'non-prime'; ``` ### 把if陳述式轉換成短路邏輯OR運算式 ```javascript= if(!options)options = {}; ``` 轉換成 ```javascript= options = options || {}; ```