<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>

          2021年,快速了解 ES2022 新特性(一)

          共 12587字,需瀏覽 26分鐘

           ·

          2021-11-08 07:16

          點(diǎn)擊上方 前端瓶子君,關(guān)注公眾號(hào)

          回復(fù)算法,加入前端編程面試算法每日一題群


          作為一個(gè)后端的菜菜,其實(shí)應(yīng)該多寫(xiě)點(diǎn)后端的東西,奈何同學(xué)們都喜歡看點(diǎn)前端的文章。這就沒(méi)法子了??,前兩天看到掘金群里有位同學(xué)不知道在哪兒看ES的新特性和ES規(guī)范與新特性的對(duì)應(yīng)關(guān)系。我覺(jué)得我的機(jī)會(huì)來(lái)了??,忙了兩天,今天抽點(diǎn)時(shí)間給大家科普一下,順便講講 ES2016-ES2022 到底有啥內(nèi)容,順便復(fù)習(xí)一下,加深印象。

          ES是啥?

          ES的全稱(chēng)是ECMAScript,由 ECMA國(guó)際[3] (前身為歐洲計(jì)算機(jī)制造商協(xié)會(huì))在標(biāo)準(zhǔn) ECMA-262[4] 中定義的腳本語(yǔ)言規(guī)范,從2015年起,每年一個(gè)版本,到 ES2022 已經(jīng)是第十三個(gè)版本了。我們常用的 JavaScript 就是 ECMA-262[5] 標(biāo)準(zhǔn)的實(shí)現(xiàn)和拓展。現(xiàn)在我直接貼一個(gè)官網(wǎng)的地址 ECMAScript[6] 吧,詳細(xì)的內(nèi)容大家可以直接查看官網(wǎng)的介紹。我就不過(guò)多介紹這個(gè)東西了。水字?jǐn)?shù)沒(méi)必要。。。??

          盡管 ES2022 的還沒(méi)有正式發(fā)布,但是提案已經(jīng)完成,板上釘釘。下面我就按照大概的情況列一下各個(gè)ES版本提案的全稱(chēng)、發(fā)布年份、縮寫(xiě)信息等,這樣大家就不會(huì)迷惑ES的命名了。

          全稱(chēng) 發(fā)布年份 縮寫(xiě) / 簡(jiǎn)稱(chēng)
          ECMAScript 2015 2015 ES2015 / ES6
          ECMAScript 2016 2016 ES2016 / ES7
          ECMAScript 2017 2017 ES2017 / ES8
          ECMAScript 2018 2018 ES2018 / ES9
          ECMAScript 2019 2019 ES2019 / ES10
          ECMAScript 2020 2020 ES2020 / ES11
          ECMAScript 2021 2021 ES2021 / ES12
          ECMAScript 2022 2022 ES2022 / ES13

          有的同學(xué)可能會(huì)有這樣的疑問(wèn),為啥 ES2015 對(duì)應(yīng)的是 ES6 ,而不是 ES5 呢? 這里說(shuō)明一下,這兩個(gè)數(shù)字不是同一個(gè)東西,2015 代表的是發(fā)布的日期,而 6 表示的是ECMAScript語(yǔ)言規(guī)范的第幾個(gè)版本。這樣不懂的同學(xué)可能就明白了,再回頭一看上面的表格,這樣印象就更加深刻了。

          ES2016 - ES2022的特性

          騷話不多說(shuō),下面我們直接開(kāi)始吧。我會(huì)將 ES2016 - ES2022 的內(nèi)容分成一段段舉例演示,內(nèi)容主要以 Github已完成 提案[7] 上的順序講解。(PS: 沒(méi)有 ES2015 / ES6 ,直接 ES2016 / ES7 起步)

          ES2016 / ES7

          Array.prototype.includes 數(shù)組是否包含某個(gè)元素

          這個(gè)特性很多小伙伴肯定都用過(guò),這個(gè)主要的作用是查找一個(gè)元素是否在數(shù)組中。在這個(gè)方法沒(méi)出來(lái)之前,偷懶同學(xué)可能是通過(guò)數(shù)組的 indexOf 方法來(lái)做校驗(yàn)的

          [123].indexOf(1) >= 0

          // 結(jié)果: true
          復(fù)制代碼

          正常情況下,indexOf 方法并沒(méi)有啥毛病,但是這個(gè)方法存在一個(gè)漏洞,當(dāng)需要查看的元素是 NaN 時(shí),這個(gè) indexOf 方法將不能夠準(zhǔn)確的判斷出元素是否被包含在數(shù)組中

          [12NaN].indexOf(NaN) >= 0

          // 結(jié)果: false
          復(fù)制代碼

          另外一個(gè)問(wèn)題是,indexOf 這個(gè)方法主要想表明的是一個(gè)元素在數(shù)組中的 索引位置 而不是確定一個(gè)元素是否包含在數(shù)組中,所以勤快的同學(xué)一般會(huì)通過(guò)手寫(xiě)一個(gè)循環(huán)方法來(lái)處理這個(gè)問(wèn)題,但是引用這個(gè)方法又比較麻煩,直接套在原型上?不敢不敢。。。

          function contains(array, val{
              for (var i = 0; i < array.length; i++) {
                  if (array[i] === val) {
                      return true;
                  }
              }
              return false;
          }
          復(fù)制代碼

          現(xiàn)在我們有了 includes 方法,上述的問(wèn)題都將解決,并且更加好使,我們來(lái)測(cè)試一下以下代碼,大家可以腦補(bǔ)一下下面的結(jié)果

          console.log([123].includes(2) === true);
          console.log([123].includes(4) === false);
          console.log([12NaN].includes(NaN) === true);

          console.log([12-0].includes(+0) === true);
          console.log([12, +0].includes(-0) === true);

          console.log(["a""b""c"].includes("a") === true);
          console.log(["a""b""c"].includes("a"1) === false);
          復(fù)制代碼

          我們現(xiàn)在公布答案,上面的七個(gè)結(jié)果均為 true 。毋庸置疑。。。

          Exponentiation operator 冪運(yùn)算

          這個(gè)沒(méi)有啥好講的,直接看下面的代碼片段就明白了

          let squared = 2 ** 2;
          // same as: 2 * 2

          let cubed = 2 ** 3;
          // same as: 2 * 2 * 2

          let a = 2;
          a **= 2;
          // same as: a = a * a;

          let b = 3;
          b **= 3;
          // same as: b = b * b * b;
          復(fù)制代碼

          ES2017 / ES8

          Object.values / Object.entries 對(duì)象值、對(duì)象對(duì)

          這個(gè)也沒(méi)啥好說(shuō)的,Object.values 方法返回一個(gè)給定對(duì)象自身的所有可枚舉屬性值的數(shù)組,值的順序與使用for...in循環(huán)的順序相同(區(qū)別在于 for-in 循環(huán)枚舉原型鏈中的屬性),看代碼

          let point = {x12y6};
          Object.values(point);

          // 結(jié)果: [12, 6]
          復(fù)制代碼

          Object.entries 方法返回一個(gè)給定對(duì)象自身可枚舉屬性的鍵值對(duì)數(shù)組,其排列與使用 for...in 循環(huán)遍歷該對(duì)象時(shí)返回的順序一致(區(qū)別在于 for-in 循環(huán)還會(huì)枚舉原型鏈中的屬性)。

          聽(tīng)起來(lái)有點(diǎn)繞,咱們直接看代碼

          let point = {x12y6};
          Object.entries(point);

          // 結(jié)果: [["x", 12], ["y", 6]]
          復(fù)制代碼

          字符串也同樣ok

          Object.entries("hello world");

          // 結(jié)果: [["0","h"],["1","e"],["2","l"],["3","l"],["4","o"],["5"," "],["6","w"],["7","o"],["8","r"],["9","l"],["10","d"]]
          復(fù)制代碼

          來(lái)試試順序

          let object = {
              3"z",
              1"x",
              2"y",
              z3,
              x1,
              y2
          };

          for (var key in object) {
              console.log(key);
          }
          // 1
          // 2
          // 3
          // z
          // x
          // y

          Object.entries(object);

          // 結(jié)果: [["1","x"],["2","y"],["3","z"],["z",3],["x",1],["y",2]]
          復(fù)制代碼

          我們可以看到,輸出結(jié)果和上面我們的方法描述一致(其排列與使用 for...in 循環(huán)遍歷該對(duì)象時(shí)返回的順序一致)。同時(shí),這兒還有個(gè)隱藏的 bufffor...in 會(huì)對(duì)數(shù)字的類(lèi)型的 key 升序放在前面,不相信的同學(xué)自己也可以嘗試一下哦。

          String.prototype.padStart / String.prototype.padEnd 填充字符串

          這兩個(gè)方法還是比較常見(jiàn)的,我可以指定一個(gè)字符最大的寬度,當(dāng)字符串超過(guò)最大長(zhǎng)度則截?cái)嗵鎿Q字符,保留左邊(padStart)或者右邊(padEnd)的內(nèi)容當(dāng)字符串寬度沒(méi)有達(dá)到的時(shí)候,將會(huì)在開(kāi)始(padStart )或者結(jié)尾(padEnd )填充指定的字符,填充字符未指定默認(rèn)是一個(gè) 空格(U+0020) ,它主要用來(lái)格式化字符串,當(dāng)然你也可以把它玩兒出花來(lái)。我們先來(lái)看一下定義

          interface String {
              /**
               * 用給定字符串(可能重復(fù))填充當(dāng)前字符串,以使生成的字符串達(dá)到給定長(zhǎng)度。填充從當(dāng)前字符串的開(kāi)始(左)開(kāi)始應(yīng)用。
               *
               * @param maxLength 填充當(dāng)前字符串后所得字符串的長(zhǎng)度。如果此參數(shù)小于當(dāng)前字符串的長(zhǎng)度,則當(dāng)前字符串將按原樣返回。
               *
               * @param fillString 用于填充當(dāng)前字符串的字符串。如果此字符串太長(zhǎng),將截?cái)嗨?yīng)用最左邊的部分。參數(shù)的默認(rèn)值為' '(U+0020)。
               */

              padStart(maxLength: number, fillString?: string): string;

              /**
               * 用給定字符串(可能重復(fù))填充當(dāng)前字符串,以使生成的字符串達(dá)到給定長(zhǎng)度。從當(dāng)前字符串的末尾(右側(cè))應(yīng)用填充。
               *
               * @param maxLength 填充當(dāng)前字符串后所得字符串的長(zhǎng)度。如果此參數(shù)小于當(dāng)前字符串的長(zhǎng)度,則當(dāng)前字符串將按原樣返回。
               *
               * @param fillString 用于填充當(dāng)前字符串的字符串。如果此字符串太長(zhǎng),將截?cái)嗨?yīng)用最左邊的部分。參數(shù)的默認(rèn)值為' '(U+0020)。
               */

              padEnd(maxLength: number, fillString?: string): string;
          }
          復(fù)制代碼

          有的同學(xué)可能對(duì)上面的超出長(zhǎng)度的截?cái)嗟暮x比較模糊,下面我們直接上手,看下輸出就明白了

          'foo'.padStart(5)
          // 結(jié)果: '  foo'
          'foo'.padStart(5'-')
          // 結(jié)果: '--foo'
          'foo'.padStart(5'xyz')
          // 結(jié)果: 'xyfoo' (超出長(zhǎng)度,'z' 字符被截?cái)嗳サ袅耍A袅俗筮叢糠值膬?nèi)容)
          'bar'.padEnd(5)
          // 結(jié)果: 'bar  '
          'bar'.padEnd(5'-')
          // 結(jié)果: 'bar--'
          'bar'.padEnd(5'xyz')
          // 結(jié)果: 'barxy' (超出長(zhǎng)度,'z' 字符被截?cái)嗳サ袅耍A袅俗筮叢糠值膬?nèi)容)

          // 原字符串長(zhǎng)度超出最大字符串長(zhǎng)度情況下
          'foo'.padStart(2'xyz')
          // 結(jié)果: 'foo'
          'foo'.padStart(2'xyz')
          // 結(jié)果: 'foo'
          復(fù)制代碼

          Object.getOwnPropertyDescriptors 獲取自身屬性描述符

          這個(gè)方法我們可以根據(jù)方法含義來(lái)理解,那就是獲取自身屬性的描述符。它常常配合 Object.create() 這個(gè)方法,來(lái)實(shí)現(xiàn)拷貝對(duì)象屬性/對(duì)象屬性特性以及原型。在理解這個(gè)方法之前,我們得知道啥是屬性描述符。我們先定義一個(gè)對(duì)象打印一手,直接獲取了對(duì)象的屬性的描述符

          let point = {
              x12,
              y16,
              move({x, y}) {
                  this.x = x;
                  this.y = y;
              }
          }
          Object.getOwnPropertyDescriptors(point);
          // {
          //     x: {
          //         configurable: true,
          //         enumerable: true,
          //         value: 12,
          //         writable: true,
          //         [[Prototype]]: Object
          //     }, 
          //     y: {
          //         configurable: true,
          //         enumerable: true,
          //         value: 16,
          //         writable: true, 
          //         [[Prototype]]: Object
          //     },
          //     move: {
          //         configurable: true,
          //         enumerable: true,
          //         value: f move({x,y}),
          //         writable: true, 
          //         [[Prototype]]: Object
          //     },
          //     [[Prototype]]: Object
          // }

          let c = {}
          Object.getOwnPropertyDescriptors(c);
          // {}
          復(fù)制代碼

          我們從上面的結(jié)果中,可以發(fā)現(xiàn):如果對(duì)象為空,那么獲取到的描述就是個(gè)空對(duì)象,如果有屬性或者方法,會(huì)對(duì)每個(gè)屬性進(jìn)行描述,包含

          • configurable: 當(dāng)且僅當(dāng)該屬性的 configurable 鍵值為 true 時(shí),該屬性的描述符才能夠被改變,同時(shí)該屬性也能從對(duì)應(yīng)的對(duì)象上被刪除。默認(rèn)為 false
          • enumerable: 當(dāng)且僅當(dāng)該屬性的 enumerable 鍵值為 true 時(shí),該屬性才會(huì)出現(xiàn)在對(duì)象的枚舉屬性中。默認(rèn)為 false
          • value: 該屬性對(duì)應(yīng)的值。可以是任何有效的 JavaScript 值( 數(shù)值對(duì)象函數(shù) 等)。默認(rèn)為 undefined
          • writable: 當(dāng)且僅當(dāng)該屬性的 writable 鍵值為 true 時(shí),屬性的值,也就是上面的 value,才能被賦值運(yùn)算符改變。默認(rèn)為 false

          詳情我們可以在 Object.defineProperty\(\)[8] 這兒看到,這里的屬性描述符實(shí)際上是給 Object.defineProperty\(\)[9] 的第三個(gè)參數(shù)用的。從上面的例子中,我們可以看出,我們直接定義一個(gè)對(duì)象 point ,并且直接設(shè)置屬性方法,對(duì)象屬性默認(rèn) configurableenumerablewritable 設(shè)置為 true

          我們現(xiàn)在給上面的例子再修改一下,加深理解。我們先遍歷打印一下 pointkey

          for (var key in point) {
              console.log(key);
          }
          // x
          // y
          // move
          復(fù)制代碼

          接著使用 Object.defineProperty\(\)[10] 方法修改一下 pointmove 方法的描述符

          Object.defineProperty(point, 'move', {
              enumerablefalse
          });
          for (var key in point) {
              console.log(key);
          }
          // x
          // y
          復(fù)制代碼

          我們可以看到 move 這個(gè)方法在 for..in 中已經(jīng)沒(méi)有打印名稱(chēng)了。我們用 Object.getOwnPropertyDescriptor\(\)[11] 這個(gè) 老方法 再看看 move 的屬性描述符

          Object.getOwnPropertyDescriptor(point, 'move');
          //{
          //    configurable: true,
          //    enumerable: false,
          //    value: f move({x,y}),
          //    writable: true, 
          //    [[Prototype]]: Object
          //}
          復(fù)制代碼

          符合我們的預(yù)期。大家看明白了屬性描述符,那對(duì)這個(gè)新增的方法就能理解的明明白白了

          Async functions 異步方法

          這個(gè)感覺(jué)沒(méi)有啥好寫(xiě)的,懂得都懂。asyncawait 相當(dāng)于一個(gè)語(yǔ)法糖,被 async 標(biāo)記的方法將會(huì)返回一個(gè) Promise 對(duì)象。我們可以在一個(gè) async 標(biāo)記的方法中使用 await 一個(gè) Promise 對(duì)象,當(dāng) Promise 結(jié)束之后才執(zhí)行下一語(yǔ)句,這讓我們可以在 async 標(biāo)記的方法中用同步的方法來(lái)書(shū)寫(xiě)異步的 Promise 。我們簡(jiǎn)單舉一個(gè)例子

          async function a() {
              return "a";
          }
          function b() {
              return new Promise((resolve, reject) => {
                  setTimeout(() => {
                      resolve("b");
                  }, 3000);
              });
          }
          async function c() {
              return "c";
          }
          async function d() {
              let a = await a();
              console.log(a);
              let b = await b();
              console.log(b);
              let c = await c();
              console.log(c);
          }
          console.log(d())

          // 結(jié)果:
          // Promise { <pending> } `async` 標(biāo)記的方法返回了一個(gè) `Promise` 對(duì)象
          // a
          // b  等待三秒之后繼續(xù)輸出后續(xù)內(nèi)容
          // c

          復(fù)制代碼

          異步的方法同步的方式寫(xiě),看起來(lái)很美好,但實(shí)際使用中還是有一點(diǎn)點(diǎn)問(wèn)題。我之前寫(xiě)過(guò)一篇 JS中優(yōu)雅的使用async await[12] ,有興趣的小伙伴可以去瞅瞅。

          Shared memory and atomics 共享內(nèi)存和原子

          這個(gè)是給瀏覽器的規(guī)范,我們可以通過(guò) SharedArrayBufferAtomics 增強(qiáng) js 的并行能力,想要了解的同學(xué)可以翻看 SharedArrayBuffer[13]Atomics[14] ,因?yàn)槌霈F(xiàn)的場(chǎng)景很少,我就不細(xì)講了。加油啊各位。

          總結(jié)

          文章到這兒暫時(shí)告一段落,我一開(kāi)始膨脹了,文章最開(kāi)始的標(biāo)題是 一文快速了解ES2016 \- ES2022新特性 。但是寫(xiě)下來(lái),照我這個(gè)講解程度,光 ES7ES8 的篇幅就已經(jīng)很長(zhǎng)了,所以我現(xiàn)在打算將 ES2016 \- ES2022 的新特性拆分成多篇來(lái)寫(xiě),目的呢,為了更好的讓大家理解這些內(nèi)容(才不是呢??),給大家和我自己一點(diǎn)余地。嘻嘻

          關(guān)于本文

          作者:盡管如此世界依然美麗

          https://juejin.cn/post/7021183043679289352

          最后

          歡迎關(guān)注【前端瓶子君】??ヽ(°▽°)ノ?
          回復(fù)「算法」,加入前端編程源碼算法群,每日一道面試題(工作日),第二天瓶子君都會(huì)很認(rèn)真的解答喲!
          回復(fù)「交流」,吹吹水、聊聊技術(shù)、吐吐槽!
          回復(fù)「閱讀」,每日刷刷高質(zhì)量好文!
          如果這篇文章對(duì)你有幫助,在看」是最大的支持
           》》面試官也在看的算法資料《《
          “在看和轉(zhuǎn)發(fā)”就是最大的支持
          瀏覽 51
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  亚洲超碰在线 | 国产精品卡一卡二卡三卡4在线 | 亚洲福利视频在线 | 亚洲欧美日韩一级片 | 成人麻豆日韩在无码视频 |