1.數值分割符 _
ES2021 引入了數值分割符 _,在數值組之間提供分隔,使一個長數值讀起來更容易,Chrome 已經供了對數值分割符的支持,可以在瀏覽器里試起來,
let number = 100_0000_0000_0000 // 0太多了不用數值分割符眼睛看花了
console.log(number) // 輸出 100000000000000
此外,十進制的小數部分也可以使用數值分割符,二進制、十六進制里也可以使用數值分割符,
0x11_1 === 0x111 // true 十六進制
0.11_1 === 0.111 // true 十進制的小數
0b11_1 === 0b111 // true 二進制
2.逗號運算子 ,
什么,逗號也可以是運算子嗎?是的,曾經看到這樣一個簡單的函式,將陣列的第一項和第二項調換,并回傳兩項之和:
function reverse(arr) {
return [arr[0], arr[1]]=[arr[1], arr[0]], arr[0] + arr[1]
}
const list = [1, 2]
reverse(list) // 回傳 3,此時 list 為[2, 1]
逗號運算子對它的每個運算元求值(從左到右),并回傳最后一個運算元的值,
expr1, expr2, expr3...
會回傳最后一個運算式 expr3 的結果,其他的運算式只會進行求值,
3.零合并運算子 ??
零合并運算子 ?? 是一個邏輯運算子,當左側的運算元為 null 或者 undefined 時,回傳右側運算元,否則回傳左側運算元,
expr1 ?? expr2
空值合并運算子一般用來為常量提供默認值,保證常量不為 null 或者 undefined,以前一般使用 || 來做這件事 variable = variable || ‘bar’,然而,由于 || 是一個布爾邏輯運算子,左側的運算元會被強制轉換成布林值用于求值,任何假值(0, ‘’, NaN, null, undefined)都不會被回傳,這導致如果你使用 0、’’、NaN 作為有效值,就會出現不可預料的后果,
正因為 || 存在這樣的問題,而 ?? 的出現就是解決了這些問題,?? 只會在左側為 undefined、null 時才回傳后者,?? 可以理解為是 || 的完善解決方案,
可以在瀏覽器中執行下面的代碼感受一下:
undefined || 'default' // 'default'
null || 'default' // 'default'
false || 'default' // 'default'
0 || 'default' // 'default'
undefined ?? 'default' // 'default'
null ?? 'default' // 'default'
false ?? 'default' // 'false'
0 ?? 'default' // 0
4. 可選鏈運算子 ?.
可選鏈運算子 ?. 允許讀取位于連接物件鏈深處的屬性的值,而不必驗證鏈中的每個參考是否有效,?. 運算子的功能類似于 . 鏈式運算子,不同之處在于,在參考為 null 或者 undefined 的情況下不會引起錯誤,該運算式短路回傳值是 undefined,
當嘗試訪問可能不存在的物件屬性時,可選鏈運算子將會使運算式更短、更簡明,
const obj = {
a: 'foo',
b: {
c: 'bar'
}
}
console.log(obj.b?.c) // 輸出 bar
console.log(obj.d?.c) // 輸出 undefined
console.log(obj.func?.()) // 不報錯,輸出 undefined
以前可能會通過 obj && obj.a && obj.a.b 來獲取一個深度嵌套的子屬性,現在可以直接 obj?.a?.b 即可,
可選鏈除了可以用在獲取物件的屬性,還可以用在陣列的索引 arr?.[index],也可以用在函式的判斷 func?.(args),當嘗試呼叫一個可能不存在的方法時也可以使用可選鏈,
呼叫一個物件上可能不存在的方法時(版本原因或者當前用戶的設備不支持該功能的場景下),使用可選鏈可以使得運算式在函式不存在時回傳 undefined 而不是直接拋例外,
const result = someInterface.customFunc?.()
5.私有方法/屬性
在一個類里面可以給屬性前面增加 # 私有標記的方式來標記為私有,除了屬性可以被標記為私有外,getter/setter 也可以標記為私有,方法也可以標為私有,
class Person {
getDesc(){
return this.#name +' '+ this.#getAge()
}
#getAge(){ return this.#age } // 私有方法
get #name(){ return 'foo' } // 私有訪問器
#age = 23 // 私有屬性
}
const a = new Person()
console.log(a.age) // undefined 直接訪問不到
console.log(a.getDesc()) // foo 23
6.位運算子 >> 與 >>>
有符號右移運算子 >> 將第一個運算元向右移動指定的位數,多余的位移到右邊被丟棄,高位補其符號位,正數補 0,負數則補 1,因為新的最左位與前一個最左位的值相同,所以符號位(最左位)不會改變,
(0b111>>1).toString(2) // "11"
(-0b111>>1).toString(2) // "-100" 感覺跟直覺不一樣
正數的好理解,負數怎么理解呢,負數在計算機中存盤是按照補碼來存盤的,補碼的計算方式是取反加一,移位時將補碼形式右移,最左邊補符號位,移完之后再次取反加一求補碼獲得處理后的原碼,
-111 // 真值
1 0000111 // 原碼(高位的0無所謂,后面加不到)
1 1111001 // 補碼
1 1111100 // 算數右移
1 0000100 // 移位后求補碼獲得原碼
-100 // 移位后的真值
一般我們用 >> 來將一個數除 2,相當于先舍棄小數位然后進行一次 Math.floor:
10 >> 1 // 5
13 >> 1 // 6 相當于
13.9 >> 1 // 6
-13 >> 1 // -7 相當于
-13.9 >> 1 // -7
無符號右移運算子 >>>,將符號位作為二進制資料的一部分向右移動,高位始終補 0,對于正整數和算數右移沒有區別,對于負數來說由于符號位被補 0,成為正數后就不用再求補碼了,所以結果總是非負的,即便右移 0 個位元,結果也是非負的,
(0b111>>>1).toString(2) // "11"
(-0b111>>>1).toString(2) // "1111111111111111111111111111100"
7.位運算子 & 與 |
位運算子是按位進行運算,& 與、| 或、~非、^ 按位異或:
&: 1010 |: 1010 ~: 1010 ^: 1010
0110 0110 0110
---- ---- ---- ----
0010 1110 0101 1100
使用位運算子時會拋棄小數位,我們可以利用這個特性來給數字取整,比如給任意數字 & 上二進制的 32 個 1,或者 | 上 0,顯而易見后者簡單些,
所以我們可以對一個數字 | 0 來取整,負數也同樣適用
1.3 | 0 // 1
-1.9 | 0 // -1
判斷奇偶數除了常見的取余 % 2 之外,也可以使用 & 1,來判斷二進制數的最低位是不是 1,這樣除了最低位之外都被置 0,取余的結果只剩最低位,是不是很巧妙,負數也同樣適用:
const num = 3
!!(num & 1) // true
!!(num % 2) // true
8.雙位運算子 ~~
可以使用雙位運算子來替代正數的 Math.floor( ),替代負數的 Math.ceil( ),雙否定位運算子的優勢在于它執行相同的操作運行速度更快,
Math.floor(4.9) === 4 // true
// 簡寫為:
~~4.9 === 4 // true
不過要注意,對正數來說 ~~ 運算結果與 Math.floor( ) 運算結果相同,而對于負數來說與 Math.ceil( )的運算結果相同:
~~4.5 // 4
Math.floor(4.5) // 4
Math.ceil(4.5) // 5
~~-4.5 // -4
Math.floor(-4.5) // -5
Math.ceil(-4.5) // -4
PS:注意
~~(num/2)方式和num >> 1在值為負數時的差別
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/255908.html
標籤:其他
