<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ES11來了,不進來看看嘛

          共 8025字,需瀏覽 17分鐘

           ·

          2020-08-03 17:08

          前言

          ES2020 (ES11)是 ECMAScript 對應 2020 年的版本。這個版本不像 ES6 (ES2015)那樣包含大量新特性。但也添加了許多有趣且有用的特性。本文以簡單的代碼示例來介紹 ES2020新特性。這樣,你可以很快理解這些新功能,而不需要多么復雜的解釋,好了,廢話不多說我們進入正文?

          私有變量

          類的主要作用之一是將我們的代碼包含在可重用的模塊中。所以會在許多不同地方使用到同一個類,但是又的類里面的一些屬性,為了安全或者是其他的目的,不想讓其他的類能夠去訪問他,修改他,只能他自己用,對于一些學過c#,java等語言的同學來說是比較好理解的,就是 Private一個訪問修飾符,那么在我們的js當中該怎么辦了,

          別擔心,他們有的咱js也有,在ES11中也為我們提供了私有變量,通過在變量或函數(shù)前面添加一個哈希符號#,可以將它們設為私有屬性,只在類內(nèi)部可用。

          這是我們普通的一個類

          class?Money{
          ??constructor(money){
          ????this.money=money;
          ??}
          }
          let?RMB=new?Money(999);
          RMB.money=999999;//這還了得,怎么可以隨便改錢的金額呢
          console.log(RMB.money);//可以通過對象的形式去訪問

          由于安全,我們不能讓其他的類來隨便更改我們類里面的屬性的值,我們可以使用 ?私有屬性,是只能在類里面進行訪問

          class?Money{
          ??????#money=0;//聲明這個屬性是私有屬性
          ??????constructor(money){
          ????????this.#money=money;
          ??????}
          ????}
          ????let?RMB=new?Money(999);
          ????//RMB.#money=999999;//Uncaught?SyntaxError:?Private?field?'#money'?must?be?declared?in?an?enclosing?class,
          ????console.log(RMB.#money);//Uncaught?SyntaxError:?Private?field?'#money'?must?be?declared?in?an?enclosing?class

          上面的代碼報錯了,哭唧唧,拿不到私有屬性的值了,怎么辦??

          我需要使用我類里面的錢,怎么獲取

          我們可以在類里面寫兩個方法,取數(shù)據(jù),寫入數(shù)據(jù),可以進行修改,但是你不能任意改,必須通過我的方法去改,我們可以看看下面的代碼

          class?Money{
          ??#money=0;//聲明這個屬性是私有屬性
          ??constructor(money){
          ????this.#money=money;
          ??}
          ??getMoney(){//獲取值
          ????return?this.#money;
          ??}
          ??setMoney(money){//寫入值
          ????this.#money+=money;
          ??}
          }
          let?RMB=new?Money(999);
          RMB.setMoney(8848)
          console.log(RMB.getMoney());

          好了,私有變量(屬性),我們就說到這里了,下面我們來看看空值合并運算符吧!

          空值合并運算符

          在我們平常的工作中,在取一個對象里面的屬性,如果這個屬性沒有值,我們會這樣給他一個默認值

          let?user={
          ??name:'Symbol盧',
          ??age:18
          }
          console.log(user.name,"name")//Symbol盧?name
          console.log(user.like,"like")//undefined?"like"
          //對象里面沒有這個屬性的時候,他一個默認值
          console.log(user.like?||?'寫代碼',"like2")//寫代碼?like2?

          //ES2020?的???空值合并操作符
          console.log(user.sex??'男',"sex");??//男?sex
          ??//不存在這個sex屬性,就會走后面的默認值,如果存在這個sex屬性,就不會走后面的默認值

          **空值合并運算符(*??*)**是一個邏輯運算符。當左側(cè)操作數(shù)為 null 或 undefined 時,其返回右側(cè)的操作數(shù)。否則返回左側(cè)的操作數(shù)。

          ??和 || 的區(qū)別是什么呢??

          他們兩個最大的區(qū)別就是 ' '和 0,??的左側(cè) 為 ' '或者為 0 的時候,依然會返回左側(cè)的值;

          || 會對左側(cè)的數(shù)據(jù)進行boolean類型轉(zhuǎn)換,所以' '和 0 會被轉(zhuǎn)換成false,返回右側(cè)的值

          可選鏈操作符

          減少訪問深層對象時判斷屬性存不存在的問題。

          const?a?=?{};

          console.log(a.b.c);?//?這里會報Err,?無法從undefined中得到c

          console.log(person?.profile?.name);?//?""
          console.log(person?.hobby?.work);?//?undefined

          console.log(person?.hobby?.work????"no?Work");?//?no?Work

          可選鏈中的 ? 表示如果問號左邊表達式有值, 就會繼續(xù)查詢問號后面的字段。根據(jù)上面可以看出,用可選鏈可以大量簡化類似繁瑣的前置校驗操作,而且更安全。

          注意?. 不能用來賦值。

          賦值,我們通常采用 ?可選鏈操作符空值合并運算符 進行搭配使用

          let?user={
          ??name:'Symbol盧',
          ??age:18,
          ??skill:{
          ????Web:{
          ??????html:'50%',
          ??????css:'60%',
          ??????js:'80%'
          ????},
          ????Server:{
          ??????node:'80%',
          ??????php:'50%',
          ??????net:'60%'
          ????}
          ??}
          }
          console.log(user.name,"name")//Symbol盧?name
          console.log(user.like,"like")//undefined?"like"
          //我們平常的工作中,會這樣使用,當我們的對象里面沒有這個屬性的時候,這樣給他一個默認值
          console.log(user.like?||?'寫代碼',"like2")//寫代碼?like2?

          //ES2020?的??

          console.log(user.sex??'男',"sex");??//不存在這個sex屬性,就會走后面的默認值,如果存在這個sex屬性,就不會走后面的默認值

          console.log(user.skill.Web.js,"js")//80%?js
          //console.log(user.skill.Database.MySql,"MySql")//Uncaught?TypeError:?Cannot?read?property?'MySql'?of?undefined
          //空值合并運算符??與?可選鏈?相結(jié)合,可以很輕松處理多級查詢并賦予默認值問題
          console.log(user?.skill?.Database?.MySql????'88%',"MySql")

          BigInt

          關于js的浮點數(shù)的一個精度問題,最典型的就是 ?0.1+0.2!= 0.3

          console.log(0.1+0.2,'0.1+0.2')//0.30000000000000004?"0.1+0.2"
          console.log(0.1+0.2==0.3,"0.1+0.2==0.3")//false?"0.1+0.2==0.3"

          JavaScript可以處理的最大數(shù)字是2 ^ 53,通過MAX_SAFE_INTEGER可以查出這個值:

          JavaScript 中 Number 類型只能安全的表示-(2^53 -1)2^53 -1 范的值,即 Number.MIN_SAFE_INTEGERNumber.MAX_SAFE_INTEGER,超出這個范圍的整數(shù)計算或者表示會丟失精度。

          let?maxNum=Number.MAX_SAFE_INTEGER;
          console.log(maxNum)//9007199254740991

          let?num1=Number.MAX_SAFE_INTEGER+1;
          let?num2=Number.MAX_SAFE_INTEGER+2;
          console.log(num1==num2,"num1==num2")//true??超過這個范圍,就精度丟失了

          為解決此問題,ES2020 提供一種新的數(shù)據(jù)類型:BigInt。使用 BigInt 有兩種方式:

          1. 在整數(shù)字面量后面加n
          let?bigIntNum1=9007199254740999n;
          console.log(typeof?bigIntNum1)//bigint
          1. 使用 BigInt 函數(shù)。
          let?bigIntNum2=BigInt(90071992547409999);
          console.log(typeof?bigIntNum2)//bigint

          接下來我們再對兩位數(shù)進行判斷:

          console.log(bigIntNum1==bigIntNum2)//false
          //已結(jié)解決了之前超過這個精度不能進行計算的問題

          我們再通過 BigInt, 我們可以安全的進行大數(shù)整型計算。

          let?BigNum=bigIntNum1+bigIntNum2;
          console.log(BigNum.toString())//99079191802150999

          注意:

          1. BigInt 是一種新的數(shù)據(jù)原始(primitive)類型。注意標準數(shù)字與BigInt 數(shù)字不能混合使用。
          typeof?9007199254740993n;?//?->?'bigint'
          1. 盡可能避免通過調(diào)用函數(shù) BigInt 方式來實例化超大整型。因為參數(shù)的字面量實際也是 Number 類型的一次實例化,超出安全范圍的數(shù)字,可能會引起精度丟失。

          動態(tài)導入

          在項目中,某些功能可能很少使用,而導入所有依賴項可能只是浪費資源。現(xiàn)在可以使用async / await在需要時動態(tài)導入依賴項,可以在初始化的時候不全部加載邏輯資源,只進行按需加載,這樣可以讓首屏的渲染速度更快,雖然我們的前端工程化項目使用的webpack已經(jīng)很好支持了按需導入,但是現(xiàn)在能夠在2020正式的進入ES的規(guī)范,我們的js也是越來越強大了。

          demo.js 導出模塊:

          export?const?sum=(num1,num2)=>num1+num2;

          動態(tài)導入:

          let?fun=async(num1,num2)=>{
          ??let?model=await?import('./demo.js');
          ??console.log(model.sum(num1,num2),"兩個數(shù)的和")
          }
          fun(8,9)//17?"兩個數(shù)的和"

          //報錯
          //Access?to?script?at?'file:///C:/Users/Administrator/Desktop/es11Demo/demo.js'?from?origin?'null'?has?been?blocked?by?CORS?policy:?Cross?origin?requests?are?only?supported?for?protocol?schemes:?http,?data,?chrome,?chrome-extension,?https.
          ???//demo.js:1?Failed?to?load?resource:?net::ERR_FAILED
          ???//demo.html:13?Uncaught?(in?promise)?TypeError:?Failed?to?fetch?dynamically?imported?module:?file:///C:/Users/Administrator/Desktop/es11Demo/demo.js

          //報錯需要在http服務器環(huán)境下,才可以

          在當前項目的 根目錄上創(chuàng)建http服務器 (電腦里面已經(jīng)有node環(huán)境)

          npm i http-server -g ? ?安裝依賴

          然后在目錄 里面 執(zhí)行 http-server

          globalThis

          JavaScript 在不同的環(huán)境獲取全局對象有不同的方式,NodeJS 中通過 global, Web 中通過 window, self 等,有些甚至通過 this 獲取,但通過 this 是及其危險的,this 在 JavaScript 中異常復雜,它嚴重依賴當前的執(zhí)行上下文,這些無疑增加了獲取全局對象的復雜性。

          • 全局變量 window:是一個經(jīng)典的獲取全局對象的方法。但是它在 Node.js 和 Web Workers 中并不能使用

          • 全局變量 self:通常只在 Web Workers 和瀏覽器中生效。但是它不支持 Node.js。

          • 全局變量 global:只在 Node.js 中生效

          我們寫的一個js文件,可能在瀏覽器上運行,也可能在node環(huán)境下運行,也可能在 ?Web Workers 環(huán)境中運行,

          這時候的這個全局變量就不統(tǒng)一我們可以使用以下的方法去做一個判斷,過去獲取全局對象,可通過一個全局函數(shù):

          var?getGlobal?=?function?()?{
          ??if?(typeof?self?!==?'undefined')?{?return?self;?}
          ??if?(typeofwindow?!==?'undefined')?{?returnwindow;?}
          ??if?(typeof?global?!==?'undefined')?{?return?global;?}
          ??thrownewError('unable?to?locate?global?object');
          };
          var?globals?=?getGlobal();

          而到我們的ES11中為我們提供了 globalThis

          globalThis 目的就是提供一種標準化方式訪問全局對象,有了 globalThis后,你可以在任意上下文,任意時刻都能獲取到全局對象。

          globalThis 提供了一個標準的方式來獲取不同環(huán)境下的全局 this 對象(也就是全局對象自身),所以不用擔心運行環(huán)境。

          //?worker.js
          console.log(globalThis?===?self)?//true
          //?node.js
          console.log(globalThis?===?global)?//true
          //?瀏覽器
          console.log(globalThis?===?window)?//true

          Promise.all 缺陷

          都知道 Promise.all 具有并發(fā)執(zhí)行異步任務的能力。但它的最大問題就是如果其中某個任務出現(xiàn)異常(reject),所有任務都會掛掉,Promise 直接進入 reject 狀態(tài)。

          想象這個場景:你的頁面有三個區(qū)域,分別對應三個獨立的接口數(shù)據(jù),使用 Promise.all 來并發(fā)三個接口,如果其中任意一個接口服務異常,狀態(tài)是 reject,這會導致頁面中該三個區(qū)域數(shù)據(jù)全都無法渲染出來,因為任何 reject 都會進入 catch 回調(diào), 很明顯,這是無法接受的,如下:

          let?a=?new?Promise((resolve,reject)=>{
          ??//異步操作...
          ??resolve({?code:?200,msg:"請求成功"})
          })
          let?b=?new?Promise((resolve,reject)=>{
          ??//異步操作...
          ??resolve({?code:?200,msg:"請求成功"})
          })
          let?c=?new?Promise((resolve,reject)=>{
          ??//異步操作...
          ??reject({?code:?500,msg:"服務器出現(xiàn)異常"})
          })
          //使用Promise.all?進行并發(fā)執(zhí)行異步任務
          Promise.all([a,b,c])
          .then((res)?=>?{
          ????//?只有?上面所有的請求都是?resolve?(成功)?的時候才會進入此回調(diào)中
          ????console.log(res,"res")
          })
          .catch((error)?=>?{
          ????//?上面的請求中,只要有一個是reject?(失敗)?就會進入此回調(diào)
          ????console.log(error,"error")
          ????//?error:?{code:?500,?msg:?"服務異常"}
          })

          Promise.allSettled

          當我們處理多個promise時,尤其是當它們相互依賴時,記錄每個事件在調(diào)試中發(fā)生的錯誤可能很有用。使用Promise.allSettled,它會創(chuàng)建一個新的promise,在所有promise完成后返回一個包含每個promise結(jié)果的數(shù)組。

          let?a=?new?Promise((resolve,reject)=>{
          ??//異步操作...
          ??resolve({?code:?200,msg:"請求成功"})
          })
          let?b=?new?Promise((resolve,reject)=>{
          ??//異步操作...
          ??resolve({?code:?200,msg:"請求成功"})
          })
          let?c=?new?Promise((resolve,reject)=>{
          ??//異步操作...
          ??reject({?code:?500,msg:"服務器出現(xiàn)異常"})
          })
          //使用進行并發(fā)請求
          Promise.allSettled([a,b,c]).then((data=>{
          ??console.log(data,"data")
          }))

          //?返回的數(shù)據(jù)中?,status:?"fulfilled"?表示請求成功,status:?"rejected"?表示請求失敗

          Promise.allSettled 的優(yōu)勢

          Promise.allSettled跟``Promise.all類似 都是進行并發(fā)請求,但是,我們在上面的兩個例子中,顯然是已經(jīng)看到了他們的一些區(qū)別,在使用Promise.all進行并發(fā)請求的時候,只要有一個請求出現(xiàn)問題(異常),所有的請求正常的也都不能拿到數(shù)據(jù),但是在我們的業(yè)務的開發(fā)中,我們需要保障我們業(yè)務的最大的可訪問性,就是在我們執(zhí)行并發(fā)任務中,不管我這個并發(fā)任務中的一任何個任務是正常還是異常,我們都需要拿到返回的對應的狀態(tài),在ES11中Promise.allSettled就為我們解決了這個問題,它和Promise.all類似,參數(shù)接受一個Promise的數(shù)組,返回一個新的Promise,也就是說當Promise全部處理完成后,我們可以拿到每個Promise的狀態(tài), 而不管是否處理成功。我們可以在then里面通過filter來過濾出想要的業(yè)務邏輯結(jié)果,這樣就解決了Promise.all` 的缺陷。


          最后



          如果你覺得這篇內(nèi)容對你挺有啟發(fā),我想邀請你幫我三個小忙:

          1. 點個「在看」,讓更多的人也能看到這篇內(nèi)容(喜歡不點在看,都是耍流氓 -_-)

          2. 歡迎加我微信「qianyu443033099」拉你進技術群,長期交流學習...

          3. 關注公眾號「前端下午茶」,持續(xù)為你推送精選好文,也可以加我為好友,隨時聊騷。

          點個在看支持我吧,轉(zhuǎn)發(fā)就更好了


          瀏覽 60
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美A片在线观看 | 欧美黄色一级 | 亚洲无码福利导航 | 男女操操| 欧美视频日本麻豆 |