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

          11 個(gè) ES2022(ES13)中驚人的 JavaScript 新特性

          共 9584字,需瀏覽 20分鐘

           ·

          2022-07-31 23:11

          英文 | https://javascript.plainenglish.io/es13-javascript-features-eed7ed2f1497

          翻譯 | 楊小愛


          與許多其他編程語言一樣,JavaScript 也在不斷發(fā)展,每年,該語言都會通過新功能變得更強(qiáng)大,讓開發(fā)人員編寫更具表現(xiàn)力和簡潔的代碼。
          讓我們探索 ECMAScript 2022 (ES13) 中添加的最新功能,并查看它們的使用示例以便我們更好地理解它們。
          1、類字段聲明
          在 ES13 之前,類字段只能在構(gòu)造函數(shù)中聲明,與許多其他語言不同,我們不能在類的最外層范圍內(nèi)聲明或定義它們。
          class Car {  constructor() {    this.color = 'blue';    this.age = 2;  }}const car = new Car();console.log(car.color); // blueconsole.log(car.age); // 2

          ES13 消除了這個(gè)限制,現(xiàn)在我們可以編寫如下代碼:

          class Car {  color = 'blue';  age = 2;}const car = new Car();console.log(car.color); // blueconsole.log(car.age); // 2

          2、私有方法和字段

          以前,不能在類中聲明私有成員,成員通常以下劃線 (_) 為前綴,表示它是私有的,但仍然可以從類外部訪問和修改。

          class Person {  _firstName = 'Joseph';  _lastName = 'Stevens';  get name() {    return `${this._firstName} ${this._lastName}`;  }}const person = new Person();console.log(person.name); // Joseph Stevens// Members intended to be private can still be accessed// from outside the classconsole.log(person._firstName); // Josephconsole.log(person._lastName); // Stevens// They can also be modifiedperson._firstName = 'Robert';person._lastName = 'Becker';console.log(person.name); // Robert Becker

          使用 ES13,我們現(xiàn)在可以將私有字段和成員添加到類中,方法是在其前面加上井號 (#),試圖從類外部訪問它們會導(dǎo)致錯誤:

          class Person {  #firstName = 'Joseph';  #lastName = 'Stevens';  get name() {    return `${this.#firstName} ${this.#lastName}`;  }}const person = new Person();console.log(person.name);// SyntaxError: Private field '#firstName' must be// declared in an enclosing classconsole.log(person.#firstName);console.log(person.#lastName);

          請注意,這里拋出的錯誤是語法錯誤,發(fā)生在編譯時(shí),因此沒有部分代碼運(yùn)行,編譯器甚至不希望您嘗試從類外部訪問私有字段,因此,它假定您正在嘗試聲明一個(gè)。

          3、await運(yùn)算符

          在 JavaScript 中,await 運(yùn)算符用于暫停執(zhí)行,直到 Promise 被解決(履行或拒絕)。

          以前,我們只能在 async 函數(shù)中使用此運(yùn)算符 - 使用 async 關(guān)鍵字聲明的函數(shù)。我們無法在全球范圍內(nèi)這樣做。

          function setTimeoutAsync(timeout) {  return new Promise((resolve) => {    setTimeout(() => {      resolve();    }, timeout);  });}// SyntaxError: await is only valid in async functionsawait setTimeoutAsync(3000);

          使用 ES13,現(xiàn)在我們可以:

          function setTimeoutAsync(timeout) {  return new Promise((resolve) => {    setTimeout(() => {      resolve();    }, timeout);  });}// Waits for timeout - no error thrownawait setTimeoutAsync(3000);

          4、靜態(tài)類字段和靜態(tài)私有方法

          我們現(xiàn)在可以在 ES13 中為類聲明靜態(tài)字段和靜態(tài)私有方法,靜態(tài)方法可以使用 this 關(guān)鍵字訪問類中的其他私有/公共靜態(tài)成員,實(shí)例方法可以使用 this.constructor 訪問它們。

          class Person {  static #count = 0;  static getCount() {    return this.#count;  }  constructor() {    this.constructor.#incrementCount();  }  static #incrementCount() {    this.#count++;  }}const person1 = new Person();const person2 = new Person();console.log(Person.getCount()); // 2

          5、類靜態(tài)塊

          ES13 允許在創(chuàng)建類時(shí)定義只執(zhí)行一次的靜態(tài)塊,這類似于其他支持面向?qū)ο缶幊痰恼Z言(如 C# 和 Java)中的靜態(tài)構(gòu)造函數(shù)。

          一個(gè)類的類主體中可以有任意數(shù)量的靜態(tài) {} 初始化塊,它們將與任何交錯的靜態(tài)字段初始值設(shè)定項(xiàng)一起按照聲明的順序執(zhí)行,我們可以在靜態(tài)塊中使用超屬性來訪問超類的屬性。

          class Vehicle {  static defaultColor = 'blue';}class Car extends Vehicle {  static colors = [];  static {    this.colors.push(super.defaultColor, 'red');  }  static {    this.colors.push('green');  }}console.log(Car.colors); // [ 'blue', 'red', 'green' ]

          6、私人領(lǐng)域的人體工程學(xué)品牌檢查

          我們可以使用這個(gè)新特性來檢查一個(gè)對象中是否有一個(gè)特定的私有字段,使用 in 運(yùn)算符。

          class Car {  #color;  hasColor() {    return #color in this;  }}const car = new Car();console.log(car.hasColor()); // true;

          in 運(yùn)算符可以正確區(qū)分不同類的同名私有字段:

          class Car {  #color;  hasColor() {    return #color in this;  }}class House {  #color;  hasColor() {    return #color in this;  }}const car = new Car();const house = new House();console.log(car.hasColor()); // true;console.log(car.hasColor.call(house)); // falseconsole.log(house.hasColor()); // trueconsole.log(house.hasColor.call(car)); // false

          7、at() 方法進(jìn)行索引

          我們通常在 JavaScript 中使用方括號 ([]) 來訪問數(shù)組的第 N 個(gè)元素,這通常是一個(gè)簡單的過程,我們只訪問數(shù)組的 N - 1 屬性。

          const arr = ['a', 'b', 'c', 'd'];console.log(arr[1]); // b

          但是,如果我們想使用方括號訪問數(shù)組末尾的第 N 個(gè)項(xiàng)目,我們必須使用 arr.length - N 的索引。

          const arr = ['a', 'b', 'c', 'd'];// 1st element from the endconsole.log(arr[arr.length - 1]); // d// 2nd element from the endconsole.log(arr[arr.length - 2]); // c

          新的 at() 方法讓我們可以更簡潔、更有表現(xiàn)力地做到這一點(diǎn),要訪問數(shù)組末尾的第 N 個(gè)元素,我們只需將負(fù)值 -N 傳遞給 at()。

          const arr = ['a', 'b', 'c', 'd'];// 1st element from the endconsole.log(arr.at(-1)); // d// 2nd element from the endconsole.log(arr.at(-2)); // c

          除了數(shù)組,字符串和 TypedArray 對象現(xiàn)在也有 at() 方法。

          const str = 'Coding Beauty';console.log(str.at(-1)); // yconsole.log(str.at(-2)); // tconst typedArray = new Uint8Array([16, 32, 48, 64]);console.log(typedArray.at(-1)); // 64console.log(typedArray.at(-2)); // 48

          8、 RegExp 匹配索引

          這個(gè)新功能允許我們指定我們想要獲取給定字符串中 RegExp 對象匹配的開始和結(jié)束索引。

          以前,我們只能在字符串中獲取正則表達(dá)式匹配的起始索引。

          const str = 'sun and moon';const regex = /and/;const matchObj = regex.exec(str);// [ 'and', index: 4, input: 'sun and moon', groups: undefined ]console.log(matchObj);

          我們現(xiàn)在可以指定一個(gè) d 正則表達(dá)式標(biāo)志來獲取匹配開始和結(jié)束的兩個(gè)索引。

          const str = 'sun and moon';const regex = /and/d;const matchObj = regex.exec(str);/**[  'and',  index: 4,  input: 'sun and moon',  groups: undefined,  indices: [ [ 4, 7 ], groups: undefined ]] */console.log(matchObj);

          設(shè)置 d 標(biāo)志后,返回的對象將具有包含開始和結(jié)束索引的 indices 屬性。

          9、Object.hasOwn() 方法

          在 JavaScript 中,我們可以使用 Object.prototype.hasOwnProperty() 方法來檢查對象是否具有給定的屬性。

          class Car {  color = 'green';  age = 2;}const car = new Car();console.log(car.hasOwnProperty('age')); // trueconsole.log(car.hasOwnProperty('name')); // false

          但是,這種方法存在一定的問題,一方面,Object.prototype.hasOwnProperty() 方法不受保護(hù) - 它可以通過為類定義自定義 hasOwnProperty() 方法來覆蓋,該方法可能具有與 Object.prototype.hasOwnProperty() 完全不同的行為。

          class Car {  color = 'green';  age = 2;  // This method does not tell us whether an object of  // this class has a given property.  hasOwnProperty() {    return false;  }}const car = new Car();console.log(car.hasOwnProperty('age')); // falseconsole.log(car.hasOwnProperty('name')); // false

          另一個(gè)問題是,對于使用 null 原型創(chuàng)建的對象(使用 Object.create(null)),嘗試對其調(diào)用此方法會導(dǎo)致錯誤。

          const obj = Object.create(null);obj.color = 'green';obj.age = 2;// TypeError: obj.hasOwnProperty is not a functionconsole.log(obj.hasOwnProperty('color'));

          解決這些問題的一種方法是使用調(diào)用 Object.prototype.hasOwnProperty Function 屬性上的 call() 方法,如下所示:

          const obj = Object.create(null);obj.color = 'green';obj.age = 2;obj.hasOwnProperty = () => false;console.log(Object.prototype.hasOwnProperty.call(obj, 'color')); // trueconsole.log(Object.prototype.hasOwnProperty.call(obj, 'name')); // false

          這不是很方便,我們可以編寫一個(gè)可重用的函數(shù)來避免重復(fù)自己:

          function objHasOwnProp(obj, propertyKey) {  return Object.prototype.hasOwnProperty.call(obj, propertyKey);}const obj = Object.create(null);obj.color = 'green';obj.age = 2;obj.hasOwnProperty = () => false;console.log(objHasOwnProp(obj, 'color')); // trueconsole.log(objHasOwnProp(obj, 'name')); // false

          不過沒有必要,因?yàn)槲覀兛梢允褂眯碌膬?nèi)置 Object.hasOwn() 方法。與我們的可重用函數(shù)一樣,它接受對象和屬性作為參數(shù),如果指定的屬性是對象的直接屬性,則返回 true。否則,它返回 false。

          const obj = Object.create(null);obj.color = 'green';obj.age = 2;obj.hasOwnProperty = () => false;console.log(Object.hasOwn(obj, 'color')); // trueconsole.log(Object.hasOwn(obj, 'name')); // false

          10、錯誤原因

          錯誤對象現(xiàn)在有一個(gè) cause 屬性,用于指定導(dǎo)致即將拋出的錯誤的原始錯誤。這有助于為錯誤添加額外的上下文信息并幫助診斷意外行為,我們可以通過在作為第二個(gè)參數(shù)傳遞給 Error() 構(gòu)造函數(shù)的對象上設(shè)置 cause 屬性來指定錯誤的原因。

          function userAction() {  try {    apiCallThatCanThrow();  } catch (err) {    throw new Error('New error message', { cause: err });  }}try {  userAction();} catch (err) {  console.log(err);  console.log(`Cause by: ${err.cause}`);}

          11、從最后一個(gè)數(shù)組查找

          在 JavaScript 中,我們已經(jīng)可以使用 Array find() 方法在數(shù)組中查找通過指定測試條件的元素,同樣,我們可以使用 findIndex() 來查找此類元素的索引。

          雖然 find() 和 findIndex() 都從數(shù)組的第一個(gè)元素開始搜索,但在某些情況下,最好從最后一個(gè)元素開始搜索。

          在某些情況下,我們知道從最后一個(gè)元素中查找可能會獲得更好的性能。例如,這里我們試圖在數(shù)組中獲取值 prop 等于 y 的項(xiàng)目。使用 find() 和 findIndex():

          const letters = [  { value: 'v' },  { value: 'w' },  { value: 'x' },  { value: 'y' },  { value: 'z' },];const found = letters.find((item) => item.value === 'y');const foundIndex = letters.findIndex((item) => item.value === 'y');console.log(found); // { value: 'y' }console.log(foundIndex); // 3

          這行得通,但是由于目標(biāo)對象更靠近數(shù)組的尾部,如果我們使用 findLast() 和 findLastIndex() 方法從末尾搜索數(shù)組,我們可以讓這個(gè)程序運(yùn)行得更快。

          const letters = [  { value: 'v' },  { value: 'w' },  { value: 'x' },  { value: 'y' },  { value: 'z' },];const found = letters.findLast((item) => item.value === 'y');const foundIndex = letters.findLastIndex((item) => item.value === 'y');console.log(found); // { value: 'y' }console.log(foundIndex); // 3

          另一個(gè)用例可能要求我們專門從末尾搜索數(shù)組以獲取正確的項(xiàng)目。例如,如果我們想在數(shù)字列表中查找最后一個(gè)偶數(shù), find() 和 findIndex() 會產(chǎn)生錯誤的結(jié)果:

          const nums = [7, 14, 3, 8, 10, 9];// gives 14, instead of 10const lastEven = nums.find((value) => value % 2 === 0);// gives 1, instead of 4const lastEvenIndex = nums.findIndex((value) => value % 2 === 0);console.log(lastEven); // 14console.log(lastEvenIndex); // 1

          我們可以在調(diào)用 find() 和 findIndex() 之前調(diào)用數(shù)組的 reverse() 方法來反轉(zhuǎn)元素的順序。

          但是這種方法會導(dǎo)致數(shù)組發(fā)生不必要的突變,因?yàn)?reverse() 會反轉(zhuǎn)數(shù)組的元素。避免這種突變的唯一方法是制作整個(gè)數(shù)組的新副本,這可能會導(dǎo)致大型數(shù)組出現(xiàn)性能問題。

          此外, findIndex() 仍然無法在反轉(zhuǎn)數(shù)組上工作,因?yàn)榉崔D(zhuǎn)元素也意味著更改它們在原始數(shù)組中的索引。要獲得原始索引,我們需要執(zhí)行額外的計(jì)算,這意味著編寫更多代碼。

          const nums = [7, 14, 3, 8, 10, 9];// Copying the entire array with the spread syntax before// calling reverse()const reversed = [...nums].reverse();// correctly gives 10const lastEven = reversed.find((value) => value % 2 === 0);// gives 1, instead of 4const reversedIndex = reversed.findIndex((value) => value % 2 === 0);// Need to re-calculate to get original indexconst lastEvenIndex = reversed.length - 1 - reversedIndex;console.log(lastEven); // 10console.log(reversedIndex); // 1console.log(lastEvenIndex); // 4

          在 findLast() 和 findLastIndex() 方法派上用場的情況下。

          const nums = [7, 14, 3, 8, 10, 9];const lastEven = nums.findLast((num) => num % 2 === 0);const lastEvenIndex = nums.findLastIndex((num) => num % 2 === 0);console.log(lastEven); // 10console.log(lastEvenIndex); // 4

          這段代碼更短,更易讀。最重要的是,它會產(chǎn)生正確的結(jié)果。

          結(jié)論

          所以我們已經(jīng)看到了 ES13 為 JavaScript 帶來的最新特性,使用它們來提高我們作為開發(fā)人員的工作效率,并以更簡潔和清晰的方式編寫更簡潔的代碼。如果你覺得我這篇文章對你有用的話,請記得點(diǎn)贊我,關(guān)注我,并將它分享給你身邊的朋友,也許能夠幫助到他。

          最后,感謝你的閱讀。


          學(xué)習(xí)更多技能

          請點(diǎn)擊下方公眾號


          瀏覽 39
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(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>
                  亚洲中文在线播放 | 99久久精品互换人妻 | 日本性爱一二三区 | 婷婷综合av | 丁香五月成人电影 |