--- tags: JavaScirpt, hexo部落格, 六角筆記王 title: 運算子 --- # 運算子 舉凡加減乘除都是運算子,等號也是運算子之一。 (詳細可參考 [MDN-運算子](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Guide/Expressions_and_Operators))。 - **運算子均為表達式,一定會回傳值** - 一元運算子 - `let a = 1` - 二元運算子 - `let b = 1 + 2` - 三元運算子 ```javascript let c = true console.log(c ? 'Y' : 'N') ``` - 物件增加屬性的方法 `.` ,也是一個運算子,`.`、`[]`在運算子中為**最優先**。 ## 優先性、相依性 - 運算子有其優先順序 - 乘除的優先序大於加減的優先序 - 相依性則決定了運算方向 - 絕大多數的運算子都是從左至右 - 等號賦值為從右至左 - 經典題目 : 在 JS 中執行 `6/2(2+1) = ?` :::spoiler 點我看解答~ `Uncaught TypeError: 2 is not a function` 在 JS 中這樣寫語意不清的運算式會報錯,正式應該這樣寫 `6/2*(2+1)` ::: --- ## ▶ 運算子類型 ### ✏ 比較運算子 ```javascript // 從左至右,逐一比較 console.log(3 > 2 > 1) // 3 > 2 為 true // true > 1 為 false console.log(1 > 2 > 3) // 1 < 2 為 false // false > 3 為 false ``` ### ✏ 賦值運算子 ```javascript // 從右至左,逐一賦值 let a = 1 let b = a a = b = 3 console.log(a) ``` ### ✏ 邏輯運算子 共有三種,優先順序為 `!` 大於 `&&` 大於 `||`,相依性為由左至右,而且在邏輯判斷時,**型別不會自動轉換。** #### AND `&&` - 當前者可被轉型成 false時,會回傳前者結果 - 若否,回傳後者結果 - 也因此若兩者皆為布林值,根據規則剛好與"真值表"相同 #### OR `||` - 當前者可被轉型成 true,會回傳前者結果 - 若否,回傳後者結果 - 也因此若兩者皆為布林值,根據規則剛好與"真值表"相同 #### NOT `!` - 會將布林值反轉 - 可以將 Truthy & Falthy的結果反轉 ```javascript // AND `&&` console.log( 0 && 1) // 0 console.log('0' && 1) // 1 console.log( false && 1<2) // false console.log( '' && 1) // '' console.log( true && 3>2) // true console.log( 3>2 && false) // false // OR `||` console.log(0 || 1) // 1 console.log('0' || 1) // '0' console.log( false || 1<2) // true console.log( '' || null) // null console.log( true || 3>2) // true console.log( false || 3>2 ) // true // NOT `!` console.log( !1 || 2) // 2 console.log( !null || 2) // true console.log( !null && !'') // true console.log( !null && []) // [] ``` ### ✏ Member Access `.` 這縮寫為點的運算子,可以尋找/賦予物件的屬性。 ```javascript // 物件屬性賦值 let obj = {} let b ; // Object.defineProperty 可以定義物件中某個屬性的內建屬性 Object.defineProperty(obj, 'a', { value: 3, writable: false }) b = obj.a obj.c = b = 5 console.log(obj.a, b, obj.c) // 3 5 5 // obj.a 無法被修改 // b 再度被"賦予值" // 依據運算子的優先順序,物件的成員也就是屬性,它的優先順序大於等號 // 物件 obj,會先建立了 c這個屬性,之後才被等號賦予值 ``` ### ✏ 物件傳參考賦予值 運算子與物件傳參考綜合使用。 1. 物件 e 會先建立屬性名稱 x 2. 接著依照等號運作從右至左賦值 3. 物件 e 另開了一個位址 4. 原先的物件 e 的確有新增屬性名稱 x,且被賦予物件 5. 原先的物件 e 依然被 f 參考 ```javascript let e = {n:1} let f = e e.x = e = {n:2} console.log(e.x) console.log(e.q) console.log(f.x) // undefined // undefined 物件已存在,可以直接增加屬性名稱 // 呼叫 e.q 時,不會是 'q is not defined',所以呼叫 e.x 也是一樣的,只不過物件 e 已新開參考位址 // {x:2} ``` ## 寬鬆與嚴謹模式 一個等號為賦值,兩個等號為寬鬆判斷,三個等號為嚴謹判斷。 - 寬鬆判斷 - 當兩者型別不同時,JS會嘗試轉換型別。 - 嚴謹判斷 - 當兩者型別不同時,JS不會轉換型別。 ```javascript console.log(1 == 1) // true console.log(1 == '1') // true console.log(1 === '1') // false console.log(1 != '1') // false console.log(1 !== '1') // true ``` ## ▶ 隱藏型別 / 自動轉型 在判斷是否相等時,根據模式 JS 會將型別自動轉型(踩地雷~砰!)。 - 寬鬆判斷時會自動轉型 - 字串與數字 - 布林與數字 ```javascript // 字串與數字 console.log('1' == 1 ? 'Y' : 'N') // 'Y' // 布林與數字 console.log(true == 1 ? 'Y' : 'N') // 'Y' console.log(true == 0 ? 'Y' : 'N') // 'N' console.log(false == 0 ? 'Y' : 'N') // 'Y' // JS會嘗試將布林值轉成數字 // Number(true),1 // 字串與數字 ??? console.log('false' == 0 ? 'Y' : 'N') // 'N' // JS會嘗試將字串轉成數字 // Number('false'),NaN ``` - 算數運算子會自動轉型 ```javascript= console.log('1' + 1) // 字串 console.log('1' - 1) // 數字 console.log('1' * 2) // 數字 console.log('1' / 2) // 數字 ``` ### ✏ 包裹物件 它們的型別為物件,JS在相等判斷時會利用這些來轉型,像是這些 : - Number() - String() - Boolean() ### ✏ Truthy & Falthy 這邊指得是在某個函式中的參數,若放入以下其中一種**單一值**,其值被判定後的結果,與相等判斷、邏輯判斷概念不太一樣。 - 參數其值為單一數字、字串、物件、陣列、建構函式、Infinity、-Infinity以及 `true`,均為**真值**。 - 參數其值為 `false`、`0`、`""`、`null`、`undefined` 和 `NaN` 均為**假值**。 - 也就是說,除了假值之外,其餘均為真值。 ```javascript let x = 1 // 可自由替換 if (x) { console.log('被判定為 true,故為真值') } else { console.log('被判定為 false,故為假值') } console.log(Boolean(x)) ``` ### ✏ 真假值 - 函式預設值 請修改以下函式,當函式未給值時,不讓它成為假值。 ```javascript let x = 500 const fn = (y) => { x += y console.log(`本次儲存 ${y} 元!,您共有 ${x} 元。`) } fn() // 本次儲存 undefined 元!,您共有 NaN 元。" // undefined,其為函式參數預設值 // 數值與 undefined相加,會變成 NaN ``` 修改函式後 ```javascript let x = 500 const fn = (y) => { y = (y || y === 0) ? y: 500; x += y console.log(`本次儲存 ${y} 元!,您共有 ${x} 元。`) } fn() // "本次儲存 500 元!,您共有 1000 元。" ``` ## 參考來源 > 1. 六角學院 JS核心篇 - 運算子章節 > 2. [MDN - Object.defineProperty()](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty) > 3. [MDN - Truthy(真值)](https://developer.mozilla.org/zh-CN/docs/Glossary/Truthy) > 4. [MDN - 預設參數( Default parameters )](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Functions/Default_parameters) > 5. [SimonAllen - Day17 傳值by value與傳址by reference](https://ithelp.ithome.com.tw/articles/10192342) > 6. [Yi-Ning - JavaScript 核心篇 學習筆記: Chap.33 — 未定義的物件屬性預設值](https://medium.com/@yining1204/javascript-%E6%A0%B8%E5%BF%83%E7%AF%87-%E5%AD%B8%E7%BF%92%E7%AD%86%E8%A8%98-chap-33-%E6%9C%AA%E5%AE%9A%E7%BE%A9%E7%9A%84%E7%89%A9%E4%BB%B6%E5%B1%AC%E6%80%A7%E9%A0%90%E8%A8%AD%E5%80%BC-59406399c521) > 7. [Jimmy - Day 13 物件與點](https://ithelp.ithome.com.tw/articles/10205918) > 8. [Kuro Hsu - 重新認識 JavaScript: Day 08 Boolean 的真假判斷](https://ithelp.ithome.com.tw/articles/10191343) {%hackmd S1DMFioCO %}