一文快速詳解ES6~ES12的全部特性!

2022-07-22 14:01:54
本篇文章給大家整理分享一下ECMAScript特性,帶大家花一個小時,迅速瞭解ES6~ES12的全部特性。有一定的參考價值,有需要的朋友可以參考一下,希望對大家有所幫助。

作為一個喜歡動手敲程式碼的小菜鳥,我認為程式碼應該親自敲一遍,才能更好的熟記於心,所以今天就介紹一下有關 ES6 ~ ES12 的特性。如果你對ES有關的使用有盲區,或則不太瞭解新特性相信這篇文章應該能夠很好的幫助你~

為了更好地理解,我們以 案例 的模式去講解,這樣更好的理解,同時,案列也支援開發者模式下的偵錯,希望大家可以多多支援~

ECMAScript

ECMAScript是一種由Ecma國際(前身為歐洲計算機制造商協會,European Computer Manufacturers Association)通過ECMA-262標準化的指令碼程式設計語言。也可以說是JavaScript的一個標準

在程式設計師的世界只有兩個版本:ES5ES6,說是ES6,實際上是2015年釋出的,也是大前端時代正式開始的時間,也就是說以2015年為界限,2015年之前叫 ES5 ,2016年之後則統稱ES6

關於ES6特性的可看看阮一峰老師的《ES6標準入門》

ES6

宣告

let & const

let、const 和 var 之間的區別:

  • var 宣告的變數存在變數提升,而 let、const 不存在變數提升的問題。變數提升:變數是否可在宣告前呼叫
  • var 不存在塊級作用域,let 和 const 存在塊級作用域
  • var 可以重複宣告變數,let 和 const 在一個作用域內不允許重複宣告,並且 const 宣告的是一個 唯讀 的變數,並且一定要賦值

另外,當const宣告了一個物件,物件能的屬性可以改變,因為:const宣告的obj只儲存著其物件的參照地址,只要地址不變,便不會出錯

解構賦值

陣列的解構

  • 按次序排列
  • 可以從陣列中提取值,按照對應位置,對變數賦值,這種寫法屬於模式匹配
  • 可以使用 ...進行解構,代表剩餘全部
  • 如果原陣列沒有,則在對應值上可設定預設值,如果不設定,則為undefined
 let [a, b, c] = [1, 2, 3]
 console.log(a, b, c) // 1 2 3
 
 let [a, , c] = [1, 2, 3]
 console.log(a, , c) // 1 3
 
 let [a, b, ...c] = [1, 2, 3, 4, 5]
 console.log(a, b, c) // 1 2 [3, 4, 5]
 
 let [a, b, ...c] = [1]
 console.log(a, b, c) // 1 undefined []
 
 let [a = 1, b = a] = []
 const.log(a, b) // 1 1
 
 let [a = 1, b = a] = [2]
 const.log(a, b) // 2 2

物件的結構

  • 無次序行,只需變數與屬性名同名即可
  • 如果變數和物件的屬性名沒有重複,則會導致變數的值為undefined
  • 注意:,他相當於別名
 let { a, b } = { a: 1, b: 2 };
 console.log(a, b);  // 1 2
 
 let { a } = { b: 2 };
 console.log(a);  // undefined
 
 let { a, b = 2 } = { a: 1 };
 console.log(a, b);  // 1 2
 
 let { a: b = 2 } = { a: 1 };
 console.log(a);  // 不存在 a 這個變數
 console.log(b);  // 1

對字串的解構

  • 字串也可以進行解構,它相當於轉化為類似陣列的物件
  • 自帶一個 length 屬性,代表個數
 let [a, b, c, d, e] = "hello"
 console.log(a, b, c, d, e) // h e l l o
 
 let { length } = "hello"
 console.log(length) // 5

對數位和布林值的解構

  • 解構的只要不死物件或陣列,都會先將其轉化為物件,所以數位型別和布林型別也換轉化為物件
 let { toString: s } = 123;
 console.log(s === Number.prototype.toString) // true
 
 let { toString: s } = true;
 console.log(s === Boolean.prototype.toString) // true

對函數引數的解構

  • 函數的引數可以進行解構,也可以帶有預設值
  • undefined 可以觸發預設值
  • 注意兩種指定預設值的方法,一種是對變數指定,一種是對引數指定,會得到不同的答案
 let arr = [[1,2], [3, 4]]
 let res = arr.map([a, b] => a + b)
 console.log(res) // [3, 7]
 
 let arr = [1, undefined, 2]
 let res = arr.map((a = 'test') => a);
 console.log(res) // [1, 'test', 2]
 
 let func = ({x, y} = {x: 0, y: 0}) => {
    return [x, y]
 }
 console.log(func(1, 2)) // [undefined, undefined]
 console.log(func()) // [0, 0]
 console.log(func({})) // [undefined, undefined]
 console.log(func({x: 1})) // [1, undefined]
 
 
 let func = ({x=0, y=0}) => {
    return [x, y]
 }
 
 console.log(func({x:1,y:2})) // [1, 2]
 console.log(func()) // error
 console.log(func({})) // [0, 0]
  console.log(func({x: 1})) // [1, 0]

正則擴充套件

正則其實是一個非常難懂的知識點,要是有人能完全掌握,那真的是非常厲害,在這裡就簡單的說下

首先分為兩種風格:JS分格perl 分格

JS分格: RegExp()

 let re = new RegExp('a'); //查詢一個字串內是否有a
 let re = new RegExp('a', 'i'); //第一個是查詢的物件,第二個是選項

perl風格: / 規則 /選項,且可以跟多個,不分順序

 let re = /a/; //查詢一個字串內是否有a
 let re = /a/i;//第一個是查詢的物件,第二個是選項

這裡介紹一個正規表示式線上測試(附有常見的正規表示式):正則線上測試

字串擴充套件

  • Unicode大括號包含表示Unicode字元
  • codePointAt(): 返回字元對應碼點,與fromCharCode()對應
  • String.fromCharCode(): 將對對應的碼點返回為字元,與codePointAt()對應
  • String.raw():返回把字串所有變數替換且對斜槓進行跳脫的結果
  • startsWith(): 返回布林值,表示引數字串是否在原字串的頭部。
  • endsWith():返回布林值,表示引數字串是否在原字串的尾部。
  • repeat():方法返回一個新字串,表示將原字串重複n次
  • 遍歷:for-of
  • includes():返回布林值,表示是否找到了引數字串。
  • trimStart(): 方法從字串的開頭刪除空格。trimLeft() 是此方法的別名。
  • trimEnd(): 方法從一個字串的末端移除空白字元。trimRight() 是這個方法的別名。
 //Unicode
 console.log("a", "\u0061"); // a a
 console.log("d", "\u{4E25}"); // d 嚴
 
 let str = 'Domesy'
 
 //codePointAt()
 console.log(str.codePointAt(0)) // 68
 
 //String.fromCharCode()
 console.log(String.fromCharCode(68)) // D
 
 //String.raw()
 console.log(String.raw`Hi\n${1 + 2}`); // Hi\n3
 console.log(`Hi\n${1 + 2}`); // Hi 3
 
 let str = 'Domesy'
 
 //startsWith()
 console.log(str.startsWith("D")) // true
 console.log(str.startsWith("s")) // false

 //endsWith()
 console.log(str.endsWith("y")) // true
 console.log(str.endsWith("s")) // false
 
 //repeat(): 所傳的引數會自動向上取整,如果是字串會轉化為數位
 console.log(str.repeat(2)) // DomesyDomesy
 console.log(str.repeat(2.9)) // DomesyDomesy
 
 // 遍歷:for-of
  for(let code of str){
    console.log(code) // 一次返回 D o m e s y
  }
  
  //includes()
  console.log(str.includes("s")) // true
  console.log(str.includes("a")) // false
  
  // trimStart()
  const string = "   Hello world!   ";
  console.log(string.trimStart()); // "Hello world!   "
  console.log(string.trimLeft()); // "Hello world!   "
  
  // trimEnd()
  const string = "   Hello world!   ";
  console.log(string.trimEnd()); // "   Hello world!"
  console.log(string.trimRight()); // "   Hello world!"

其他

字串模板 可單行可多行插入,使用 `

 let str = `Dome
    sy`
 console.log(str) //會自動換行
 
 // Dome
 // sy

標籤模板:

 const str = {
     name: '小杜杜',
     info: '大家好‘
 }

console.log(`${str.info}, 我是`${str.name}`) // 大家好,我是小杜杜

陣列擴充套件

  • Array.of(): 將一組值轉化為陣列,返回一個新陣列,並且不考慮引數的數量或型別。
  • copyWithin():把指定位置的成員複製到其他位置,返回原陣列
  • find(): 返回第一個符合條件的值
  • findIndex(): 返回第一個符合條件的索引
  • keys():對鍵名的遍歷,返回一個遍歷器物件,可用for-of迴圈,
  • values():與 keys() 用法一樣,不過是對 鍵值 的遍歷
  • entries():與 keys() 用法一樣,不過是對 鍵值對 的遍歷
  • Array.from(): 從一個類似陣列或可迭代物件中建立一個新的陣列範例。
  • fill(): 使用制定的元素填充陣列,返回原陣列
  • includes():判斷是否包含某一元素,返回布林值,對 NaN 也有效,但不能進行定位
 let arr = [1, 2, 3, 4, 5]

 //Array.of()
 let arr1 = Array.of(1, 2, 3);
 console.log(arr1) // [1, 2, 3]
 
 //copyWithin(): 三個引數 (target, start = 0, end = this.length)
 // target: 目標的位置
 // start: 開始位置,可以省略,可以是負數。
 // end: 結束位置,可以省略,可以是負數,實際位置是end-1。
 console.log(arr.copyWithin(0, 3, 5)) // [4, 5, 3, 4, 5]
 
 //find()
 console.log(arr.find((item) => item > 3 )) // 4
 
 //findIndex()
 console.log(arr.findIndex((item) => item > 3 )) // 3
 
 // keys()
 for (let index of arr.keys()) {
     console.log(index); // 一次返回 0 1 2 3 4
 }
 
 // values()
 for (let index of arr.values()) {
     console.log(index); // 一次返回 1 2 3 4 5
 }
 
 // entries()
 for (let index of arr.entries()) {
     console.log(index); // 一次返回 [0, 1] [1, 2] [2, 3] [3, 4] [4, 5]
 }
 
  let arr = [1, 2, 3, 4, 5]
 
 // Array.from(): 遍歷的可以是偽陣列,如 String、Set結構,Node節點
 let arr1 = Array.from([1, 3, 5], (item) => {
     return item * 2;
 })
 console.log(arr1) // [2, 6, 10] 
 
 // fill(): 三個引數 (target, start = 0, end = this.length)
 // target: 目標的位置
 // start: 開始位置,可以省略,可以是負數。
 // end: 結束位置,可以省略,可以是負數,實際位置是end-1。
 console.log(arr.fill(7)) // [7, 7, 7, 7, 7]
 console.log(arr.fill(7, 1, 3)) // [1, 7, 7, 4, 5]
 
 let arr = [1, 2, 3, 4]
 
 //includes()
 console.log(arr.includes(3)) // true
 console.log([1, 2, NaN].includes(NaN)); // true

其他

擴充套件運運算元:...

 // 其作用為展開陣列
 let arr = [3, 4, 5]
 console.log(...arr) // 3 4 5
 
 let arr1 = [1, 2, ...arr]
 console.log(...arr1) // 1 2 3 4 5

物件擴充套件

  • Object.getPrototypeOf():返回物件的原型物件
  • Object.setPrototypeOf():設定物件的原型物件
  • proto:返回或設定物件的原型物件
  • Object.getOwnPropertyNames(): 返回物件自身非Symbol屬性鍵組成的陣列
  • Object.getOwnPropertySymbols(): 返回物件自身非Symbol屬性鍵組成的陣列
  • Reflect.ownKeys(): 返回物件自身全部屬性鍵組成的陣列
  • Object.is():判斷兩個物件是否相等,陣列指向的地址不同,所以只要是陣列比較,必定為 false
  • 遍歷:for-in
  • Object.keys():返回屬性名
  • Object.assign(): 用於將所有可列舉屬性的值從一個或多個源物件複製到目標物件,返回目標物件,此時的目標物件也會改變
//Object.is()
console.log(Object.is('abc', 'abc')) // true
console.log(Object.is([], [])) // false 

//遍歷:for-in
let obj = { name: 'Domesy', value: 'React' }

for(let key in obj){
    console.log(key); // 依次返回屬性值 name value
    console.log(obj[key]); // 依次返回屬性值 Domesy React
}

//Object.keys()
console.log(Object.keys(obj)) // ['name', 'value']

 //Object.assign()
 const target = { a: 1, b: 2 };
 const source = { b: 4, c: 5 };
 
 const result = Object.assign(target, source)
 
 console.log(result) // {a: 1, b: 4, c: 5}
 console.log(target) // {a: 1, b: 4, c: 5}

其他

簡潔表示法

  let a = 1;
  let b = 2;
  let obj = { a, b }
  console.log(obj) // { a: 1, b: 2 }
  
  let method = {
      hello() {
          console.log('hello')
      }
  }
  console.log(method.hello())// hello

屬性表示式: 直接用變數或者表示式來定義 Object 的 key

 let a = "b"
 let obj = {
     [a]: "c"
 }
 console.log(obj) // {b : "c"}

擴充套件運運算元 ...

  • ES9中增加了許多額外的功能,如合併、跳脫字串等操作
 // 其作用為展開陣列
 let { a, b, ...c } = { a: 1, b: 2, c: 3, d: 4};
 console.log(c) // {c: 3, d: 4}
 
 let obj1 = { c: 3 }
 let obj = { a: 1, b: 2, ...obj1}
 console.log(obj) // { a: 1, b: 2, c: 3}

數值擴充套件

  • 二進位制0b0B 開頭,表示二進位制
  • 八進位制000O 開頭,表示二進位制
  • Number.isFinite(): 用來檢查一個數值是否有限的,返回布林值
  • Number.isNaN(): 用來檢查一個數值是否是 NaN,返回布林值
  • Number.isInteger(): 用來檢查一個數值是否是整數,返回布林值
  • Number.isSafeInteger(): 用來檢查一個數值是否是「安全整數」(safe integer),返回布林值
  • Math.cbrt(): 返回立方跟
  • Math.abrt()(): 返回立方跟
  • Math.cbrt(): 返回立方跟
  • Math.clz32(): 返回數值的32位元無符號整數形式
  • Math.imul(): 返回兩個數值相乘
  • Math.fround(): 返回數值的32位元單精度浮點數形式
  • Math.hypot(): 返回所有數值平方和的平方根
  • Math.expm1(): 返回e^n - 1
  • Math.log1p(): 返回1 + n的自然對數(Math.log(1 + n))
  • Math.log10(): 返回以10為底的n的對數
  • Math.log2(): 返回以2為底的n的對數
  • Math.trunc(): 將數位的小數部分去掉,只保留整數部分
  • Math.sign(): 返回數值型別 正數為1負數為-1正零 0負零 -0NaN
  • Math.abrt(): 返回立方根
  • Math.sinh(): 返回雙曲正弦
  • Math.cosh(): 返回雙曲餘弦
  • Math.tanh(): 返回雙曲正切
  • Math.asinh(): 返回反雙曲正弦
  • Math.acosh(): 返回反雙曲餘弦
  • Math.atanh(): 返回反雙曲正切
  • Number.parseInt(): 返回值的整數部分,此方法等價於 parseInt
  • Number.parseFloat(): 返回值得浮點數部分,此方法等價於 parseFloat
 //二進位制
 console.log(0b101) // 5
 console.log(0o151) //105
 
 //Number.isFinite()
 console.log(Number.isFinite(7)); // true
 console.log(Number.isFinite(true)); // false
 
 //Number.isNaN()
 console.log(Number.isNaN(NaN)); // true
 console.log(Number.isNaN("true" / 0)); // true
 console.log(Number.isNaN(true)); // false
 
 //Number.isInteger()
 console.log(Number.isInteger(17)); // true
 console.log(Number.isInteger(17.58)); // false
 
 //Number.isSafeInteger()
 console.log(Number.isSafeInteger(3)); // true
 console.log(Number.isSafeInteger(3.0)); // true
 console.log(Number.isSafeInteger("3")); // false
 console.log(Number.isSafeInteger(3.1)); // false
 
  //Math.trunc()
 console.log(Math.trunc(13.71)); // 13
 console.log(Math.trunc(0)); // 0
 console.log(Math.trunc(true)); // 1
 console.log(Math.trunc(false)); // 0 
 
 //Math.sign()
 console.log(Math.sign(3)); // 1
 console.log(Math.sign(-3)); // -1
 console.log(Math.sign(0)); // 0
 console.log(Math.sign(-0)); // -0
 console.log(Math.sign(NaN)); // NaN
 console.log(Math.sign(true)); // 1
 console.log(Math.sign(false)); // 0
 
 //Math.abrt()
 console.log(Math.cbrt(8)); // 2
 
  //Number.parseInt()
 console.log(Number.parseInt("6.71")); // 6
 console.log(parseInt("6.71")); // 6
 
 //Number.parseFloat()
 console.log(Number.parseFloat("6.71@")); // 6.71
 console.log(parseFloat("6.71@")); // 6.71

  • 函數引數尾逗號:允許函數最後一個引數有尾逗號
  • 引數預設賦值具體的數值
 //引數預設賦值具體的數值
 let x = 1
 function fun(x, y = x){
    console.log(x, y)
 }
 function fun1(c, y = x){
    console.log(c, x, y)
 }
 fun(2); //2 2
 fun1(1); //1 1 1

其他

Rest引數(擴充套件運運算元 ...)

 function fun(...arg){
   console.log(arg) // [1, 2, 3, 4]
 }
 
 fun(1, 2, 3, 4)

箭頭函數

  • 以 => 定義函數
 let arrow = (v) => v + 2
 console.log(arrow(1)) // 3

箭頭函數與普通函數的區別

  • 箭頭函數和普通函數的樣式不同,箭頭函數語法更加簡潔、清晰,箭頭函數是 =>定義函數,普通函數是 function定義函數
  • Set 沒有鍵只有值,可以認為 鍵和值 都一樣
  • 箭頭函數其實是沒有 this 的,箭頭函數中的 this 只取決包裹箭頭函數的第一個普通函數的 this。
  • 箭頭函數沒有自己的arguments。在箭頭函數中存取arguments實際上獲得的是外層區域性(函數)執行環境中的值。
  • call、apply、bind 並不會影響其 this 的指向。
  • 箭頭函數的this指向上下文 ,而 普通函數的this並非指向上下文,需要時加入 bind(this)

Set

Set 是ES6中新的資料結構,是類似陣列,但成員的值是唯一的,沒有重複的值

宣告:const set = new Set()

屬性:

  • size:返回 Set 物件中值的個數

方法:

  • add(): 在Set物件尾部新增一個元素。返回該Set物件
  • delete(): 移除Set的中與這個值相等的元素,有則返回true,無則返回false
  • clear(): 清楚Set的所有元素
  • has(): 是否存在這個值,如果存在為 true,否則為false
  • keys():以屬性值遍歷器的物件
  • values():以屬性值遍歷器的物件
  • entries():以屬性值和屬性值遍歷器的物件
  • forEach():遍歷每個元素

特別注意:

  • 遍歷器的為iterator物件,按插入順序,為 [Key, Value] 形式
  • 加入 Set 的值不會發生型別轉化,所以1和」1「是兩個不同的值
  • 在Set內部是通過 === 來判斷,也就是說,兩個物件永遠不可能相同,原因是地址不同
  • 唯一的區別是 NaN
 let list = new Set()
 
 //add()
 list.add("1")
 list.add(1)
 console(list) // Set(2) {1, "1"}
 
 //size
 console(list.size) // 2
 
 //delete()
 list.delete("1")
 console(list) // Set(1) {1}
 
 //has()
 list.has(1) // true
 list.has(3) // false
 
 //clear()
 list.clear()
 console(list) // Set(0) {}
 
 let arr = [{id: 1}, {id: 2}, {id: 3}]
 let list = new Set(arr)
 
 // keys()
 for (let key of list.keys()) {
    console.log(key); // 以此列印:{id: 1} {id: 2} {id: 3}
 }
 
 //values()
 for (let key of list.values()) {
    console.log(key); // 以此列印:{id: 1} {id: 2} {id: 3}
 }
 
 //entries()
 for (let data of list.entries()) {
    console.log(data); // 以此列印:[{id: 1},{id: 1}] [{id: 2},{id: 2}] [{id: 3},{id: 3}]
 }
 
 //forEach
 list.forEach((item) => {
    console.log(item)// 以此列印:{id: 1} {id: 2} {id: 3}
 });

應用:

陣列去重

  • 需要注意一點的是 new Set 無法去除物件
 let arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a'];
 
 console.log([...new Set(arr)]) 
 //或 
 console.log(Array.from(new Set(arr)))
 //  [1, 'true', true, 15, false, undefined, null, NaN, 'NaN', 0, 'a']

可求並集,交集和差集

 let a = new Set([1, 2, 3])
 let b = new Set([2, 3, 4])
 
 //並集
 console.log(new Set([...a, ...b])) // Set(4) {1, 2, 3, 4}
 
 //交集
 console.log(new Set([...a].filter(v => b.has(v)))) // Set(2) {2, 3}
 
 //差集
 new Set([...a].filter(v => !b.has(v))) //  Set(1) {1}

對映集合

 let set = new Set([1,2,3])
 console.log(new Set([...set].map(v => v * 2))) // Set(3) {2, 4, 6}

WeakSet

定義: 和Set的結構,但成員值只能為物件

宣告: const set = new WeakSet()

方法:

  • add(): 在WeakSet物件尾部新增一個元素。返回該範例
  • delete(): 移除WeakSet的中與這個值相等的元素,
  • has(): 是否存在這個值,如果存在為 true,否則為false

注意:

  • WeakSet 成員的物件都是弱參照,即垃圾回收機制不考慮該物件的應用。簡單地說WebSet 的物件無法遍歷
  • 好處是,再刪除範例的時候,不會出現記憶體洩露

Map

推薦指數: ⭐️⭐️

Map 是ES6中新的資料結構,是類似物件,成員鍵是任何型別的值

宣告:const map = new Map()

屬性:

  • constructor: 建構函式,返回Map
  • size:返回 Map 範例中值的個數

方法:

  • set(): 新增Map後的一個鍵值對,返回範例
  • get(): 返回鍵值對
  • delete(): 移除Map的中與這個值相等的元素,有則返回true,無則返回false
  • clear(): 清楚Map的所有元素
  • has(): 是否存在這個值,如果存在為 true,否則為false
  • keys():以屬性鍵遍歷器的物件
  • values():以屬性值遍歷器的物件
  • entries():以屬性鍵和屬性值遍歷器的物件
  • forEach():遍歷每個元素

特別注意:

  • 對同一個物件的參照,被視為一個鍵
  • 相同的鍵,會進行覆蓋
 let map = new Map()
 
 //set()
 map.set('a', 1)
 map.set('b', 2)
 console.log(map) // Map(2) {'a' => 1, 'b' => 2}
 
 //get
 map.get("a") // 1
 
 //size
 console.log(map.size) // 2
 
 //delete()
 map.delete("a") // true
 console.log(map) // Map(1) {'b' => 2}
 
 //has()
 map.has('b') // true
 map.has(1) // false
 
 //clear()
 map.clear()
 console.log(map) // Map(0) {}
 
 let arr = [["a", 1], ["b", 2], ["c", 3]]
 let map = new Map(arr)
 
 // keys()
 for (let key of map.keys()) {
    console.log(key); // 以此列印:a b c
 }
 
 //values()
 for (let value of map.values()) {
    console.log(value); // 以此列印:1 2 3
 }
 
 //entries()
 for (let data of map.entries()) {
    console.log(data); // 以此列印:["a", 1] ["b", 2] ["c", 3]
 }
 
 //forEach
 map.forEach((item) => {
    console.log(item)// 以此列印:1 2 3
 });

WeakMap

定義: 和Map的結構,但成員值只能為物件

宣告: const set = new WeakMap()

方法:

  • set(): 新增鍵值對,返回範例
  • get(): 返回鍵值對
  • delete(): 刪除鍵值對,如果存在為 true,否則為false
  • has(): 是否存在這個值,如果存在為 true,否則為false

Symbol(原始型別)

Symbol 是ES6中引入的原始資料型別,代表著獨一無二

宣告:const sy = Stmbol()

引數: string(可選)

方法:

  • Symbol.for(): 建立以引數作為描述的Symbol值,如存在此引數則返回原有的Symbol值(先搜尋後建立,登記在全域性環境)
  • Symbol.keyFor():返回已登記的Symbol值的描述(只能返回Symbol.for()key)
  • Object.getOwnPropertySymbols() :返回物件中所有用作屬性名的Symbol值的陣列
 // 宣告
 let a = Symbol();
 let b = Symbol();
 console.log(a === b); // false
 
 //Symbol.for()
 let c = Symbol.for("domesy");
 let d = Symbol.for("domesy");
 console.log(c === d); // true
 
 //Symbol.keyFor()
 const e = Symbol.for("1");
 console.log(Symbol.keyFor(e)); // 1
 
 //Symbol.description
 let symbol = Symbol("es");
 console.log(symbol.description); // es
 console.log(Symbol("es") === Symbol("es")); // false
 console.log(symbol === symbol); // true
 console.log(symbol.description === "es"); // true

Proxy

Proxy用於修改某些操作的預設行為,等同於在語言層面做出修改,所以屬於一種「超程式設計」(meta programming),即對程式語言進行程式設計

可以這樣理解,Proxy就是在目標物件之前設定的一層攔截,外界想要存取都要經過這層攔截,因此提供了一種機制,可以對外界的存取進行過濾和改寫。

Proxy 在這裡可以理解為代理器

宣告: const proxy = new Proxy(target, handler)

  • target: 攔截的物件
  • handler: 定義攔截的方法

方法:

  • get(): 攔截物件屬性的讀取
  • set(): 攔截物件設定屬性,返回一個布林值
  • has(): 攔截 propKey in proxy 的操作,返回一個布林值
  • ownKeys(): 攔截物件屬性遍歷,返回一個陣列
  • deleteProperty():攔截 delete proxy[propKey] 的操作,返回一個布林值()
  • apply():攔截函數的呼叫,call 和 apply 操作
  • construct():攔截 new 命令,返回一個物件: 攔截 new 命令,返回一個物件
 let obj = {
  name: 'domesy',
  time: '2022-01-27',
  value: 1
 }
 
 let data = new Proxy(obj, {
     //get()
     get(target, key){
         return target[key].replace("2022", '2015')
     },
     
     //set()
     set(target, key, value) {
        if (key === "name") {
           return (target[key] = value);
        } else {
           return target[key];
         }
     },
     
     // has()
    has(target, key) {
        if (key === "name") {
            return target[key];
        } else {
            return false;
        }
    },
    // deleteProperty()
    deleteProperty(target, key) {
        if (key.indexOf("_") > -1) {
            delete target[key];
            return true;
        } else {
            return target[key];
        }
    },
    // ownKeys()
    ownKeys(target) {
        return Object.keys(target).filter((item) => item != "time");
    },
 })
 
 console.log(data.time) // 2015-01-27
 
 data.time = '2020'
 data.name = 'React'
 console.log(data) //Proxy {name: 'React', time: '2022-01-27', value: 1}
 
 // 攔截has()
 console.log("name" in data) // true
 console.log("time" in data) // false
 
 // 刪除deleteProperty()
 delete data.time; // true
 
 // 遍歷 ownKeys()
 console.log(Object.keys(data)); //['name', 'value']

 //apply()
 let sum = (...args) => {
    let num = 0;
    args.forEach((item) => {
        num += item;
    });
    return num;
 };

 sum = new Proxy(sum, {
    apply(target, ctx, args) {
        return target(...args) * 2;
    },
 });
 
 console.log(sum(1, 2)); // 6
 console.log(sum.call(null, 1, 2, 3)); // 12
 console.log(sum.apply(null, [1, 2, 3])); // 12
 
 //constructor()
 let User = class {
    constructor(name) {
        this.name = name;
    }
 }
 User = new Proxy(User, {
    construct(target, args, newTarget) {
        return new target(...args);
    },
  });
 console.log(new User("domesy")); // User {name: 'domesy'}

Reflect

Reflect 與 Proxy 類似,只是保持Object的預設行為

  • 將 Object 物件的一些明顯屬於語言內部的方法(比如 Object.defineProperty),放到 Reflect 物件上。
  • 現階段,某些方法同時在 Object 和 Reflect 物件上部署,未來的新方法將只部署在 Reflect 物件上
  • 修改某些 Object 方法的返回結果,讓其變得更合理。比如,Object.defineProperty(obj, name, desc)在無法定義屬性時,會丟擲一個錯誤,而 Reflect.defineProperty(obj, name, desc)則會返回 false
  • 讓Object 操作變成函數行為

Reflect 的方法與 Proxy 的方法一一對應,這裡就不進行介紹了

Class

Class: 對一類具有共同特徵的事物的抽象(建構函式語法糖)

constructor() 基本定義和生成範例

 class Parent {
     constructor(name = 'es6'){
         this.name = name
     }
 }
 let data = new Parent('domesy')
 console.log(data) // Parent { name: 'domesy'}

extends 繼承

 class Parent {
     constructor(name = 'es6'){
         this.name = name
     }
 }
 
 // 普通繼承
 class Child extends Parent {}
 console.log(new Child()) //  Child { name: 'es6'} 
 
 // 傳遞引數
 class Child extends Parent {
    constructor(name = "child") {
        super(name);
        this.type = "child";
    }
 }
 console.log(new Child('domesy')) //  Child { name: 'domesy', type: 'child'}

getter setter

  • 這個兩個方法比較重要,常常用來封裝API
  • get 和 set 是屬性,而不是方法
 class Parent {
     constructor(name = 'es6'){
         this.name = name
     }
     // getter
     get getName() {
         return 'sy' + this.name
     } 
     // setter
     set setName(value){
         this.name = value
     }
 }
 
 let data = new Parent()
 console.log(data.getName) // syes6
 
 data.setName = 'domesy'
 console.log(data.getName) // domesy

static 靜態方法

  • 靜態方法,不能在類的範例上呼叫靜態方法,而應該通過類本身呼叫
 class Parent {
     static getName = (name) => {
         return `你好!${name}`
     }
 }
 
 console.log(Parent.getName('domesy')) // 你好!domesy

靜態屬性

 class Parent {}
 Parent.type = "test";
 
 console.log(Parent.type); //test

Promise

Promise 就是為了解決「回撥地獄」問題的,它可以將非同步操作的處理變得很優雅。

Promise 可以支援多個並行的請求,獲取並行請求中的資料這個 Promise 可以解決非同步的問題,本身不能說 Promise 是非同步的

定義: 包含非同步操作結果的物件

狀態:

  • pending:[待定]初始狀態
  • fulfilled:[實現]操作成功
  • rejected: [被否決]操作失敗

注意:

  • Promise 會根據狀態來確定執行哪個方法
  • Promise 範例化時狀態預設為 pending 的,如非同步狀態異常rejected,反之fulfilled
  • 狀態轉化是單向的,不可逆轉,已經確定的狀態(fulfilled/rejected)無法轉回初始狀態(pending),而且只能是從 pending 到 fulfilled 或者 rejected

基本用法

 //普通定義
 let ajax = (callback) => {
     console.log('≈')
     setTimeout(() => {
         callback && callback.call();
     }, 1000)
 } 
 ajax(() => {
     console.log('timeout')
 })
 // 先會打出 開始執行,1s 後打出 timeout
 
 //Promise
 let ajax = () => {
    console.log("開始執行");
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve();
        }, 1000);
    });
 };
 ajax().then(() => {
    console.log("timeout"); 
 });
 // 先會打出 開始執行,1s 後打出 timeout
 
 // then()
 let ajax = () => {
    console.log("開始執行");
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve();
        }, 1000);
    });
 };
 ajax()
 .then(() => {
     return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve();
        }, 2000);
    });
 })
 .then(() => {
     console.log("timeout")
 })
 // 先會打出 開始執行,3s(1+2) 後打出 timeout
 
 // catch()
 let ajax = (num) => {
    console.log("開始執行");
    return new Promise((resolve, reject) => {
        if (num > 5) {
            resolve();
        } else {
            throw new Error("出錯了");
        }
    });
 };
 
 ajax(6)
 .then(function () {
    console.log("timeout"); //  先會打出 開始執行,1s 後打出 timeout
 })
 .catch(function (err) {
    console.log("catch", err);
 });
 
  ajax(3)
 .then(function () {
    console.log("timeout"); 
 })
 .catch(function (err) {
    console.log("catch"); //  先會打出 開始執行,1s 後打出 catch
 });

Promise.all() 批次操作

  • Promise.all(arr)用於將多個promise範例,包裝成一個新的Promise範例,返回的範例就是普通的promise
  • 它接收一個數組作為引數
  • 陣列裡可以是Promise物件,也可以是別的值,只有Promise會等待狀態改變
  • 當所有的子Promise都完成,該Promise完成,返回值是全部值得陣列
  • 有任何一個失敗,該Promise失敗,返回值是第一個失敗的子Promise結果
 //所有圖片載入完成後新增到頁面
 const loadImg = (src) => {
     return new Promise(resolve, reject) => {
        let img = document.createElement("img");
        img.src = src;
        img.onload = function () {
                resolve(img);
        };
        img.onerror = function (err) {
                reject(err);
        };
    });
 }
 
 const showImgs = (imgs) => {
     imgs.forEach((img) => {
         document.body.appendChild(img);
     })
 }
 
 Promise.all([
    loadImg("https://ss0.baidu.com/7Po3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/item/71cf3bc79f3df8dcc6551159cd11728b46102889.jpg"),
    loadImg("https://ss0.baidu.com/7Po3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/item/71cf3bc79f3df8dcc6551159cd11728b46102889.jpg"),
    loadImg("https://ss0.baidu.com/7Po3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/item/71cf3bc79f3df8dcc6551159cd11728b46102889.jpg"),
 ]).then(showImgs);

Promise.race()

  • race 與 all相似,只不過只要有一個執行完就會執行
//有一個執行完就回載入到頁面
const loadImg = (src) => {
    return new Promise(resolve, reject) => {
       let img = document.createElement("img");
       img.src = src;
       img.onload = function () {
               resolve(img);
       };
       img.onerror = function (err) {
               reject(err);
       };
   });
}

const showImgs = (imgs) => {
   let p = document.createElement("p");
   p.appendChild(img);
   document.body.appendChild(p);
}

Promise.race([
   loadImg("https://ss0.baidu.com/7Po3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/item/71cf3bc79f3df8dcc6551159cd11728b46102889.jpg"),
   loadImg("https://ss0.baidu.com/7Po3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/item/71cf3bc79f3df8dcc6551159cd11728b46102889.jpg"),
   loadImg("https://ss0.baidu.com/7Po3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/item/71cf3bc79f3df8dcc6551159cd11728b46102889.jpg"),
]).then(showImgs);

Promise的問題

  • 一旦執行,無法中途取消,鏈式呼叫多個then中間不能隨便跳出來
  • 錯誤無法在外部被捕捉到,只能在內部進行預判處理,如果不設定回撥函數,Promise內部丟擲的錯誤,不會反應到外部
  • Promise內部如何執行,監測起來很難,當處於pending狀態時,無法得知目前進展到哪一個階段(剛剛開始還是即將完成)

Generator

Generator: 是可以用來控制迭代器的函數,也是封裝多個內部狀態的非同步程式設計解決方案,也叫生成器函數

引數說明

  • yield 來控制程式內部的執行的 "暫停",並返回一個物件,這個物件包括兩個屬性:valuedone
  • 其中 value 代表值, done返回布林(如果為false,代表後續還有,為true則已完成)
  • next 來恢復程式執行
  • Generator 函數的定義不能使用箭頭函數,否則會觸發 SyntaxError 錯誤
 let data = function* (){
     yield "a";
     yield "b";
     return "c"
 }
 
 let generator = data();
 console.log(generator.next()) //{value: 'a', done: false} 
 console.log(generator.next()) //{value: 'b', done: false} 
 console.log(generator.next()) //{value: 'c', done: true} 
 console.log(generator.next()) //{value: undefined, done: true}

Iterator 遍歷器

Iterator是一種介面,為各種不同的資料結構提供統一的存取機制。任何資料結構只要部署Iterator介面,就可以完成遍歷操作(即依次處理該資料結構的所有成員)。

Iterator的作用:

  • 一是為各種資料結構,提供一個統一的、簡便的存取介面
  • 使得資料結構的成員能夠按某種次序排列
  • ES6創造了一種新的遍歷命令for...of迴圈,Iterator介面主要供for...of消費
  • for-in遍歷順序:不同的引擎已就如何迭代屬性達成一致,從而使行為標準化 ES11

注意:

  • 在ES6中,有些資料結構原生具備Iterator介面(比如陣列),即不用任何處理,就可以被for...of迴圈遍歷,有些就不行(比如物件)
  • 在ES6中,有三類資料結構原生具備Iterator介面:陣列某些類似陣列的物件SetMap結構
  • 一個為物件新增Iterator介面的例子。
 // 基本使用
 let arr = ["hello", "world"];
 let map = arr[Symbol.iterator]();
 console.log(map.next()); // {value: 'hello', done: false}
 console.log(map.next()); // {value: 'world', done: false}
 console.log(map.next()); // {value: undefined, done: true}
 
 // for of 迴圈
 let arr = ["hello", "world"];
 for (let value of arr) {
    console.log(value); // hello world
 }
 
 // 物件處理
 let obj = {
     start: [1, 5, 2],
     end: [7, 9, 6],
     [Symbol.iterator](){
         let index = 0;
         let arr = this.start.concat(this.end)
         return {
             next(){
                 if(index < arr.length){
                     return {
                         value: arr[index++],
                         done: false
                     }
                 }else{
                     return {
                         value: arr[index++],
                         done: true
                     }
                 }
             }
         }
     }
 }
 for (let key of obj) {
    console.log(key); // 1 5 2 7 9 6
 }

Decorator 裝飾器

  • 使用@符號,用來擴充套件,修改類的行為
  • 使用的時候需要引入第三方庫 如: core-decorators
 const name = (target) => {
     target.name = "domesy"
 }
 
 @name
 class Test{}
 
 console.log(Test.name) //domesy

模組化

在早期,使用立即執行函數實現模組化是常見的手段,通過函數作用域解決了命名衝突、汙染全域性作用域的問題

使用模組化的好處:

  • 解決命名衝突
  • 提供複用性
  • 提高程式碼可維護性

方案:

  • CommonJS:用於伺服器(動態化依賴)
  • AMD:用於瀏覽器(動態化依賴,使用的很少)
  • CMD:用於瀏覽器(動態化依賴,使用的很少)
  • UMD:用於瀏覽器和伺服器(動態化依賴)
  • ESM:用於瀏覽器和伺服器(靜態化依賴)

export 匯出模組

  • 預設匯出: export default Index
  • 單獨匯出: `export const name = 'domesy'
  • 按需匯出(推薦): `export { name, value, id }'
  • 改名匯出:export { name as newName }

import 匯入模組

  • 預設匯入(推薦): import Index from './Index'
  • 整體匯入: import * as Index from './Index'
  • 按需匯入(推薦): import { name, value, id } from './Index'
  • 改名匯入: import { name as newName } from './Index'
  • 自執匯入: import './Index'
  • 符合匯入(推薦): import Index, { name, value, id } from './Index'

複合模式

export命令import命令結合在一起寫成一行,變數實質沒有被匯入當前模組,相當於對外轉發介面,導致當前模組無法直接使用其匯入變數,適用於 全部子模組匯出

  • 預設匯入匯出: `export { default } from './Index'
  • 整體匯入匯出: `export * from './Index'
  • 按需匯入匯出: `export { name, value, id } from './Index'
  • 預設改具名匯入匯出: `export { default as name } from './Index'

ES7

陣列擴充套件

  • includes(): 在ES6 的基礎上增加了一個索引,代表是從哪尋找ES7
 let arr = [1, 2, 3, 4]
 
 //includes() ES6
 console.log(arr.includes(3)) // true
 console.log([1, 2, NaN].includes(NaN)); // true
 
 // includes() ES7
 console.log(arr.includes(1, 0)) // true
 console.log(arr.includes(1, 1)) // false

數值擴充套件

  • 冪運運算元:用 ** 代表 Math.pow()
 // 冪運運算元 ES7
 console.log(Math.pow(2, 3)) // 8
 console.log(2 ** 8) // 256

ES8

字元傳擴充套件

  • padStart():用於頭部補全
  • padEnd():用於尾部補全。
 let str = 'Domesy'
 
 //padStart(): 會以空格的形式補位嗎,這裡用0代替,第二個引數會定義一個模板形式,會以模板進行替換
 console.log("1".padStart(2, "0")); // 01
 console.log("8-27".padStart(10, "YYYY-0M-0D")); //  YYYY-08-27
  
 // padEnd():與padStart()用法相同
 console.log("1".padEnd(2, "0")); // 10

物件擴充套件

  • Object.values():返回屬性值
  • Object.entries():返回屬性名和屬性值的陣列
let obj = { name: 'Domesy', value: 'React' }

//Object.values()
console.log(Object.values(obj)) // ['React', 'React']

//Object.entries()
console.log(Object.entries(obj)) // [['name', 'value'], ['React', 'React']]

async await

作用: 將非同步函數改為同步函數,(Generator的語法糖)

 const func = async () => {
    let promise = new Promise((resolve, reject) => {
    setTimeout(() => {
          resolve("執行");
        }, 1000);
    });
     
      console.log(await promise);
      console.log(await 0);
      console.log(await Promise.resolve(1));
      console.log(2);
      return Promise.resolve(3);
 }
 
 func().then(val => {
      console.log(val); // 依次執行: 執行 0 1 2 3
 });

特別注意:

  • Async 函數 返回 Promise物件,因此可以使用 then
  • awit 命令, 只能用在 async 函數下,否則會報錯
  • 陣列的 forEach() 執行 async/await會失效,可以使用 for-ofPromise.all()代替
  • 無法處理 promise 返回的 reject 物件,需要使用 try catch 來捕捉

awiait 等到了之後做了什麼?

這裡分為兩種情況: 是否為 promise 物件

如果不是promise , await會阻塞後面的程式碼,先執行async外面的同步程式碼,同步程式碼執行完,再回到async內部,把這個非promise的東西,作為 await表示式的結果。

如果它等到的是一個 promise 物件,await 也會暫停async後面的程式碼,先執行async外面的同步程式碼,等著 Promise 物件 fulfilled,然後把 resolve 的引數作為 await 表示式的運算結果。

async await 與 promise 的優缺點

優點:

  • 它做到了真正的序列的同步寫法,程式碼閱讀相對容易
  • 對於條件語句和其他流程語句比較友好,可以直接寫到判斷條件裡面
  • 處理複雜流程時,在程式碼清晰度方面有優勢

缺點:

  • 用 await 可能會導致效能問題,因為 await 會阻塞程式碼,也許之後的非同步程式碼並不依賴於前者,但仍然需要等待前者完成,導致程式碼失去了並行性。

ES9

字元傳擴充套件

  • 放鬆對標籤模板裡字串跳脫的限制:遇到不合法的字串跳脫返回undefined,並且從raw上可獲取原字串。
 // 放鬆字串的限制
 const test = (value) => {
     console.log(value)
 }
 test `domesy` // ['domesy', raw: ["domesy"]]

Promise

Promise.finally()

  • 不管最後狀態如何都會執行的回撥函數
 let func = time => {
     return new Promise((res, rej) => {
         setTimeout(() => {
             if(time < 500){
                 res(time)
             }else{
                 rej(time)
             }
         }, time)
     })
 }
 
 func(300)
 .then((val) => console.log('res', val))
 .catch((erro) => console.log('rej', erro))
 .finally(() => console.log('完成'))
 // 執行結果: res 300  完成
 
  func(700)
 .then((val) => console.log('res', val))
 .catch((erro) => console.log('rej', erro))
 .finally(() => console.log('完成'))
 // 執行結果: rej 700  完成

for-await-of

for-await-of: 非同步迭代器,迴圈等待每個Promise物件變為resolved狀態才進入下一步

 let getTime = (seconds) => {
     return new Promise(res => {
         setTimeout(() => {
             res(seconds)
         }, seconds)
     })
 }
 
async function test(){
    let arr = [getTime(2000),getTime(500),getTime(1000)]
    for await (let x of arr){
        console.log(x); 
    }
}

test() //以此執行 2000  500 1000

ES10

字元傳擴充套件

  • JSON.stringify(): 可返回不符合UTF-8標準的字串(直接輸入U+2028和U+2029可輸入)
 //JSON.stringify() 升級
 console.log(JSON.stringify("\uD83D\uDE0E")); 
 console.log(JSON.stringify("\u{D800}")); // \ud800

陣列擴充套件

  • flatMap(): 方法首先使用對映函數對映每個元素,然後將結果壓縮成一個新陣列。(注:它與 map 連著深度值為1的 flat 幾乎相同,但 flatMap 通常在合併成一種方法的效率稍微高一些。)
  • flat: 方法會按照一個可指定的深度遞迴遍歷陣列,並將所有元素與遍歷到的子陣列中的元素合併為一個新陣列返回。預設為1.(應用:陣列扁平化(當輸入 Infinity 自動解到最底層))
 let arr = [1, 2, 3, 4]
 
 // flatMap()
 console.log(arr.map((x) => [x * 2])); // [ [ 2 ], [ 4 ], [ 6 ], [ 8 ] ]
 console.log(arr.flatMap((x) => [x * 2])); // [ 2, 4, 6, 8 ]
 console.log(arr.flatMap((x) => [[x * 2]])); // [ [ 2 ], [ 4 ], [ 6 ], [ 8 ] ]
 
 const arr1 = [0, 1, 2, [3, 4]];
 const arr2 = [0, 1, 2, [[[3, 4]]]];

 console.log(arr1.flat()); // [ 0, 1, 2, 3, 4 ]
 console.log(arr2.flat(2)); // [ 0, 1, 2, [ 3, 4 ] ]
 console.log(arr2.flat(Infinity)); // [ 0, 1, 2, 3, 4 ]

物件擴充套件

Object.fromEntries()

  • 返回鍵和值組成的物件,相當於Object.entries()的逆操作
  • 可以做一些資料型別的轉化

Map 轉化為 Object

 let map = new Map([
    ["a", 1],
    ["b", 2],
 ]);
 
 let obj = Object.fromEntries(map);
 console.log(obj); // {a: 1, b: 2}

Array 轉化為 Object

// 注意陣列的形式
let arr = [
    ["a", 1],
    ["b", 2],
 ]
 let obj = Object.fromEntries(arr);
 console.log(obj); // {a: 1, b: 2}

物件轉換

 let obj = {
    a: 1,
    b: 2,
    c: 3
 }
 
 let res = Object.fromEntries(
     Object.entries(obj).filter(([key, val]) => value !== 3)
 )
 
 console.log(res) //{a: 1, b: 2}

數值擴充套件

  • toString()改造:返回函數原始程式碼(與編碼一致)
 //toString()
 function test () {
     consople.log('domesy')
 }
 console.log(test.toString());
 //  function test () {
 //      consople.log('domesy')
 //  }

可選的Catch引數

在 ES10 中,try catch 可忽略 catch的引數

  let func = (name) => {
      try {
         return JSON.parse(name)
      } catch {
         return false
      }
  }
  
  console.log(func(1)) // 1
  console.log(func({a: '1'})) // false

ES11

BigInt(原始型別)

  • 新的原始資料型別:BigInt,表示一個任意精度的整數,可以表示超長資料,可以超出2的53次方
  • js 中 Number型別只能安全的表示-(2^53-1)至 2^53-1 範的值

特別注意:

  • Number型別的數位有精度限制,數值的精度只能到 53 個二進位制位(相當於 16 個十進位制位, 正負9007199254740992),大於這個範圍的整數,就無法精確表示了。
  • Bigint沒有位數的限制,任何位數的整數都可以精確表示。但是其只能用於表示整數,且為了與Number進行區分,BigInt 型別的資料必須新增字尾n。
  • BigInt 可以使用負號,但是不能使用正號
  • number型別的數位和Bigint型別的數位不能混合計算
 // Number
 console.log(2 ** 53) // 9007199254740992
 console.log(Number.MAX_SAFE_INTEGER) // 9007199254740991
 
 //BigInt
 const bigInt = 9007199254740993n
 console.log(bigInt) // 9007199254740993n
 console.log(typeof bigInt) // bigint
 console.log(1n == 1) // true
 console.log(1n === 1) // false
 const bigIntNum = BigInt(9007199254740993n)
 console.log(bigIntNum) // 9007199254740993n

1.png

基本資料型別

在ES6中一共有7種,分別是:srtingnumberbooleanobjectnullundefinedsymbol

其中 object 包含: ArrayFunctionDateRegExp

而在ES11後新增一中,為 8中 分別是:srtingnumberbooleanobjectnullundefinedsymbolBigInt

Promise

Promise.allSettled():

  • 將多個範例包裝成一個新範例,返回全部範例狀態變更後的狀態陣列(齊變更再返回)
  • 無論結果是 fulfilled 還是 rejected, 無需 catch
  • 相當於增強了 Promise.all()
 Promise.allSettled([
    Promise.reject({
      code: 500,
      msg: "服務異常",
    }),
    Promise.resolve({
      code: 200,
      data: ["1", "2", "3"],
    }),
    Promise.resolve({
      code: 200,
      data: ["4", "5", "6"],
    }),
  ]).then((res) =>{
      console.log(res) // [{ reason: {code: 500, msg: '服務異常'}, status: "rejected" },
                      // { reason: {code: 200, data: ["1", "2", "3"]}, status: "rejected" },
                      // { reason: {code: 200, data: ["4", "5", "6"]}, status: "rejected" }]
      const data = res.filter((item) => item.status === "fulfilled");
      console.log(data); // [{ reason: {code: 200, data: ["1", "2", "3"]}, status: "rejected" },
                          // { reason: {code: 200, data: ["4", "5", "6"]}, status: "rejected" }]
  })

import(): 動態匯入

  • 按需獲取的動態 import. 該類函數格式(並非繼承 Function.prototype)返回 promise 函數
  • require的區別是:require()同步載入import()非同步載入
 // then()
 let modulePage = "index.js";
 import(modulePage).then((module) => {
    module.init();
 });
 
 // 結合 async await
 (async () => {
  const modulePage = 'index.js'
  const module = await import(modulePage);
  console.log(module)
 })

globalThis

  • 全域性this,無論是什麼環境(瀏覽器,node等),始終指向全域性物件
// 瀏覽器環境
console.log(globalThis) //  window

// node
console.log(globalThis) //  global

可選鏈

  • 符號 ?代表是否存在
  • TypeScript 在 3.7 版本已實現了此功能
 const user = { name: 'domesy' }
 //ES11之前
 let a = user && user.name
 
 //現在
 let b = user?.name

空值合併運運算元

  • 處理預設值的便捷運運算元
  • 與 || 相比,空值合併運運算元 ?? 只會在左邊的值嚴格等於 null 或 undefined 時起作用。
  "" || "default value"; // default value
  "" ?? "default value"; // ""
  
 const b = 0;
 const a = b || 5;
 console.log(a); // 5
 
 const b = null // undefined
 const a = b ?? 123;
 console.log(a); // 123

ES12

字元傳擴充套件

replaceAll()

  • replace() 方法僅替換一個字串中某模式(pattern)的首個範例
  • replaceAll() 會返回一個新字串,該字串中用一個替換項替換了原字串中所有匹配了某模式的部分。
  • 模式可以是一個字串或一個正規表示式,而替換項可以是一個字串或一個應用於每個匹配項的函數。
  • replaceAll() 相當於增強了 replace() 的特性,全量替換
 let str = "Hi!,這是ES6~ES12的新特性,目前為ES12"
 
 console.log(str.replace("ES", "SY")); // Hi!,這是SY6~ES12的新特性,目前為ES12
 console.log(str.replace(/ES/g, "Sy")); // Hi!,這是Sy6~Sy12的新特性,目前為Sy12
 
 console.log(str.replaceAll("ES", "Sy")); // Hi!,這是Sy6~Sy12的新特性,目前為Sy12
 console.log(str.replaceAll(/ES/g, "Sy")); // Hi!,這是Sy6~Sy12的新特性,目前為Sy12

Promise

Promise.any()

  • 其區別於 Promise.race(), 儘管某個 promise 的 reject 早於另一個 promise 的 resolve,Promise.any() 仍將返回那個首先 resolve 的 promise。
 Promise.any([
    Promise.reject("Third"),
    Promise.resolve("Second"),
    Promise.resolve("First"),
 ])
 .then((res) => console.log(res)) // Second
 .catch((err) => console.error(err)); 
 
 Promise.any([
    Promise.reject("Error 1"),
    Promise.reject("Error 2"),
    Promise.reject("Error 3"),
 ])
 .then((res) => console.log(res))
 .catch((err) => console.error(err));
 // AggregateError: All promises were rejected
 
 Promise.any([
    Promise.resolve("Third"),
    Promise.resolve("Second"),
    Promise.resolve("First"),
 ])
 .then((res) => console.log(res)) // Third
 .catch((err) => console.error(err));

WeakRefs

  • 允許建立物件的弱參照。這樣就能夠在跟蹤現有物件時不會阻止對其進行垃圾回收。對於快取和物件對映非常有用
  • 必須用 new關鍵字建立新的 WeakRef
  • deref() 讀取參照的物件
  • 正確使用 WeakRef 物件需要仔細的考慮,最好儘量避免使用。避免依賴於規範沒有保證的任何特定行為也是十分重要的。何時、如何以及是否發生垃圾回收取決於任何給定 JavaScript 引擎的實現。
 let weakref = new WeakRef({name: 'domesy', year: 24})
 
 weakref.deref() // {name: 'domesy', year: 24}
 weakref.deref().year // 24

邏輯操作符和賦值表達

&&=

let num1 = 5;
let num2 = 10;
num1 &&= num2;
console.log(num1); // 10

// 等價於
num1 && (num1 = num2);
if (num1) {
    num1 = num2;
 }

||=

let num1;
let num2 = 10;
num1 ||= num2;
console.log(num1); // 10

// 等價於
num1 || (num1 = num2);
if (!num1) {
   num1 = num2;
}

??=

  • 空值合併運運算元 ?? 只會在左邊的值嚴格等於 null 或 undefined 時起作用
let num1;
let num2 = 10;
let num3 = null; // undefined

num1 ??= num2;
console.log(num1); // 10

num1 = false;
num1 ??= num2;
console.log(num1); // false

num3 ??= 123;
console.log(num3); // 123

// 等價於
// num1 ?? (num1 = num2);

數值分隔符

let num1 = 100000;
let num2 = 100_000;

console.log(num1); // 100000
console.log(num2); // 100000

const num3 = 10.12_34_56
console.log(num3); // 10.123456

【相關推薦:、】

以上就是一文快速詳解ES6~ES12的全部特性!的詳細內容,更多請關注TW511.COM其它相關文章!