11個ES13中令人驚嘆的JavaScript新特性總結(jié)
前言
與許多其他編程語言一樣,JavaScript 也在不斷發(fā)展。每年,該語言都會通過新功能變得更加強(qiáng)大,使開發(fā)人員能夠編寫更具表現(xiàn)力和簡潔的代碼。 小編今天就為大家介紹ES13中添加的最新功能,并查看其用法示例以更好地理解它們。
1.類
在ES13之前,類字段只能在構(gòu)造函數(shù)中聲明。與許多其他語言不同,無法在類的最外層作用域中聲明或定義它們。
class Car {
constructor() {
this.color = 'blue';
this.age = 2;
}
}
const car = new Car();
console.log(car.color); // blue
console.log(car.age); // 而ES13 消除了這個限制?,F(xiàn)在我們可以編寫這樣的代碼:
class Car {
color = 'blue';
age = 2;
}const car = new Car();
console.log(car.color); // blue
console.log(car.age); // 22.私有方法和字段
ES13以前,不可能在類中聲明私有成員。成員傳統(tǒng)上帶有下劃線 ( _) 前綴,以表明它是私有的,但仍然可以從類外部訪問和修改它。
class Person {
_firstName = 'Joseph';
_lastName = 'Stevens'; get name() {
return `${this._firstName} ${this._lastName}`;
}
}const person = new Person();
console.log(person.name); // Joseph Stevens
// 仍可以從類外部訪問 // 原本打算設(shè)為私有的成員
console.log(person._firstName); // Joseph
console.log(person._lastName); // Stevens
// 也可以修改
person._firstName = 'Robert';
person._lastName = 'Becker';console.log(person.name); // Robert Becker使用 ES13,我們現(xiàn)在可以通過在類前面添加 ( #) 來向類添加私有字段和成員。嘗試從外部訪問這些類將會引發(fā)錯誤:
class Person {
#firstName = 'Joseph';
#lastName = 'Stevens'; get name() {
return `${this.#firstName} ${this.#lastName}`;
}
}const person = new Person();
console.log(person.name);
// 語法錯誤:私有字段 '#firstName' 必須在一個外層類中聲明
console.log(person.#firstName);
console.log(person.#lastName);3.await頂層操作
在 JavaScript 中,await運(yùn)算符用于暫停執(zhí)行,直到 一個Promise被解決(執(zhí)行或拒絕)。 以前只能在async中使用此運(yùn)算符。不可以在全局作用域中直接使用await。
function setTimeoutAsync(timeout) {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, timeout);
});
}
//語法錯誤:await 僅在異步函數(shù)中有效
await setTimeoutAsync(3000);有了 ES13,現(xiàn)在我們可以:
function setTimeoutAsync(timeout) {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, timeout);
});
}
// 等待超時 - 沒有錯誤拋出
await setTimeoutAsync(3000);4.靜態(tài)類字段和靜態(tài)私有方法
現(xiàn)在可以在 ES13 中為類聲明靜態(tài)字段和靜態(tài)私有方法。靜態(tài)方法可以使用關(guān)鍵字this訪問類中的其他私有/公共靜態(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()); // 25.類靜態(tài)塊
ES13 引入了一項(xiàng)特性,允許開發(fā)者定義僅在創(chuàng)建類時執(zhí)行一次的靜態(tài)塊。這一特性與其他面向?qū)ο缶幊陶Z言(如 C# 和 Java)中的靜態(tài)構(gòu)造函數(shù)相似。
在一個類的主體中,你可以定義任意數(shù)量的靜態(tài) {} 初始化塊。它們會按照聲明的順序與任何交錯的靜態(tài)字段初始值設(shè)定項(xiàng)一起執(zhí)行。此外,你還可以通過塊中的 super 關(guān)鍵字訪問超類的靜態(tài)屬性。這為開發(fā)者提供了更多的靈活性和控制能力。
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.檢查對象中的私有字段
開發(fā)者如今可以利用這一新功能,使用運(yùn)算符in來方便地檢查對象是否包含某個特定的私有字段。
class Car {
#color; hasColor() {
return #color in this;
}
}const car = new Car();
console.log(car.hasColor()); // true;通過運(yùn)算符in,可以準(zhǔ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)); // false
console.log(house.hasColor()); // true
console.log(house.hasColor.call(car)); // false7.at() 索引方法
在 JavaScript 中,我們通常使用方括號[]來訪問數(shù)組的第 t 個元素。這個過程非常簡單,但實(shí)際上我們只是訪問了索引為 t-1 的數(shù)組屬性而已。
const arr = ['a', 'b', 'c', 'd']; console.log(arr[1]); // b
然而,當(dāng)我們希望通過方括號來訪問數(shù)組末尾的第 N 個元素時,我們需要使用索引 arr.length - N。
const arr = ['a', 'b', 'c', 'd']; // 從末尾開始第一個元素 console.log(arr[arr.length - 1]); // d // 倒數(shù)第二個元素 console.log console.log(arr[arr.length - 2]); // c
借助全新的at()方法,可以以更加精簡和富有表現(xiàn)力的方式來實(shí)現(xiàn)這一目標(biāo)。要訪問數(shù)組末尾的第N個元素,只需將負(fù)值-N作為參數(shù)傳遞給at()方法即可。
const arr = ['a', 'b', 'c', 'd']; // 從末尾開始第一個元素 console.log(arr.at(-1)); // d // 倒數(shù)第二個元素 console.log console.log(arr.at(-2)); // c
除了數(shù)組之外,字符串和TypedArray對象現(xiàn)在也有at()方法。
const str = 'Coding Beauty'; console.log(str.at(-1)); // y console.log(str.at(-2)); // tconst typedArray = new Uint8Array([16, 32, 48, 64]); console.log(typedArray.at(-1)); // 64 console.log(typedArray.at(-2)); // 48
8.正則表達(dá)式匹配索引
在ES13之前,我們只能獲取字符串中正則表達(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);
使用ES13之后,可以通過指定一個/d正則表達(dá)式標(biāo)志來獲取匹配開始和結(jié)束的兩個索引。這一特性賦予了更多的靈活性和控制能力。
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è)置標(biāo)志后d,返回的對象將具有indices包含起始索引和結(jié)束索引的屬性。
9.Object.hasOwn()方法
在 JavaScript 中,我們可以使用Object.prototype.hasOwnProperty()方法來檢查對象是否具有給定的屬性。
class Car {
color = 'green';
age = 2;
}const car = new Car();console.log(car.hasOwnProperty('age')); // true
console.log(car.hasOwnProperty('name')); // false然而,這種方法存在一些問題。首先,Object.prototype.hasOwnProperty()方法并未受到保護(hù),這意味著我們可以通過自定義的hasOwnProperty()方法來覆蓋它,而這個自定義方法可能會具有與Object.prototype.hasOwnProperty()不同的行為。需要額外注意的是這一點(diǎn)。
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')); // false
console.log(car.hasOwnProperty('name')); // false另外一個問題是,如果我們使用了 null 原型(通過 Object.create(null) 創(chuàng)建的對象),那么試圖調(diào)用該方法將會產(chǎn)生錯誤。
const obj = Object.create(null);
obj.color = 'green';
obj.age = 2;
// TypeError: obj.hasOwnProperty 不是函數(shù)
console.log(obj.hasOwnProperty('color'));為了克服這些問題,我們可以利用屬性調(diào)用方法Object.prototype.hasOwnProperty.call()來解決。具體示例如下所示:
const obj = Object.create(null); obj.color = 'green'; obj.age = 2; obj.hasOwnProperty = () => false;console.log(Object.prototype.hasOwnProperty.call(obj, 'color')); // true console.log(Object.prototype.hasOwnProperty.call(obj, 'name')); // false
這種方式并不十分便利。為了避免重復(fù),我們可以編寫一個可重用的函數(shù),這樣可以使我們的代碼更加簡潔和高效:
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')); // true
console.log(objHasOwnProp(obj, 'name')); // false現(xià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')); // true console.log(Object.hasOwn(obj, 'name')); // false
10.錯誤原因?qū)傩?/h2>
現(xiàn)在,錯誤對象已經(jīng)增加了一個cause屬性,該屬性用于指定導(dǎo)致錯誤拋出的原始錯誤。通過這種方式,我們可以為錯誤添加額外的上下文信息,從而更好地診斷意外的行為。要指定錯誤的原因,我們可以在作為構(gòu)造函數(shù)的第二個參數(shù)傳遞給Error()的對象中設(shè)置屬性來實(shí)現(xiàn)。這種方法能夠提供更豐富的錯誤追蹤和調(diào)試信息。
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.從數(shù)組最后查找
在 JavaScript 中,我們已經(jīng)可以使用Array的find()方法來查找數(shù)組中滿足指定測試條件的元素。類似地,我們也可以使用findIndex()方法來獲取滿足條件的元素的索引值。盡管find()和findIndex()都是從數(shù)組的第一個元素開始搜索,但在某些情況下,從最后一個元素開始搜索可能會更有效。
有些情況下,我們知道從數(shù)組的末尾進(jìn)行查找可能會獲得更好的性能表現(xiàn)。例如,在這里我們嘗試查找數(shù)組中prop屬性等于"value"的項(xiàng)目。這時候,可以通過使用reverse()方法將數(shù)組反轉(zhuǎn),然后使用find()和findIndex()方法來從末尾開始搜索。下面是具體的實(shí)現(xiàn)示例:
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上面的代碼可以獲取正確結(jié)果,但由于目標(biāo)對象更接近數(shù)組的尾部,如果我們使用findLast()和findLastIndex()方法來從數(shù)組的末尾進(jìn)行搜索,很可能能夠顯著提升程序的執(zhí)行效率。通過這種方式,我們可以更快地找到所需的元素或索引,從而優(yōu)化代碼性能。
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在一些特定的使用場景中,我們可能需要從數(shù)組的末尾開始搜索來獲取準(zhǔn)確的元素。舉個例子,假設(shè)我們要查找數(shù)字列表中的最后一個偶數(shù),使用find()或findIndex()方法可能會導(dǎo)致錯誤的結(jié)果:
const nums = [7, 14, 3, 8, 10, 9]; // 給出 14,而不是 10 const lastEven = nums.find((value) => value % 2 === 0); // 給出 1,而不是 4 const lastEvenIndex = nums.findIndex((value) => value % 2 === 0);console.log(lastEven); // 14 console.log(lastEvenIndex); // 1
如果我們在調(diào)用reverse()方法之前使用數(shù)組的slice()方法創(chuàng)建新的數(shù)組副本,就可以避免不必要地改變原始數(shù)組的順序。然而,在處理大型數(shù)組時,這種方法可能會導(dǎo)致性能問題,因?yàn)樾枰獜?fù)制整個數(shù)組。
此外,findIndex()方法在反轉(zhuǎn)數(shù)組時仍然無法達(dá)到預(yù)期效果,因?yàn)樵氐姆崔D(zhuǎn)會導(dǎo)致它們在原始數(shù)組中的索引改變。為了獲取元素的原始索引,我們需要進(jìn)行額外的計(jì)算,這意味著需要編寫更多的代碼來處理這種情況。
const nums = [7, 14, 3, 8, 10, 9]; // 在調(diào)用reverse()之前使用展開語法復(fù)制整個數(shù)組 // calling reverse() const reversed = [...nums].reverse(); // 正確給出 10 const lastEven = reversed.find((value) => value % 2 === 0); // 給出 1,而不是 4 const reversedIndex = reversed.findIndex((value) => value % 2 === 0); // 需要重新計(jì)算得到原始索引 const lastEvenIndex = reversed.length - 1 - reversedIndex;console.log(lastEven); // 10 console.log(reversedIndex); // 1 console.log(lastEvenIndex); // 4
使用findLast()和findLastIndex()方法在需要查找數(shù)組中最后一個符合條件的元素或索引時非常實(shí)用。它們能夠準(zhǔn)確地定位目標(biāo)對象,并且從數(shù)組末尾開始搜索,提供了高效的解決方案。
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); // 10 console.log(lastEvenIndex); // 4
結(jié)論
ES13 為 JavaScript 帶來了一系列令人振奮的新功能,我們已經(jīng)有幸見識了它們的魅力。通過運(yùn)用這些功能,開發(fā)人員的工作效率將得到極大提升,同時也能以更加簡潔、明晰的方式書寫出更加純凈、精煉的代碼。這些新特性為我們帶來了更大的靈活性和便利性,使得我們的開發(fā)過程更加高效、愉悅。
以上就是11個ES13中令人驚嘆的JavaScript新特性總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于JavaScript ES13的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
js使用DOM操作實(shí)現(xiàn)簡單留言板的方法
這篇文章主要介紹了js使用DOM操作實(shí)現(xiàn)簡單留言板的方法,涉及javascript中DOM操作的技巧,非常具有實(shí)用價值,需要的朋友可以參考下2015-04-04
javascript制作坦克大戰(zhàn)全紀(jì)錄(1)
本文寫作的目的是鞏固一下自己最近學(xué)習(xí)的js知識, 這個教程適合熟悉js基本語法和面向?qū)ο笳Z法的小伙伴學(xué)習(xí)。由于自己也是剛學(xué)js不久,所以難免出現(xiàn)錯誤。如果發(fā)現(xiàn)希望給予指正。2014-11-11
下拉菜單點(diǎn)擊實(shí)現(xiàn)連接跳轉(zhuǎn)功能的js代碼
下拉菜單點(diǎn)擊實(shí)現(xiàn)連接跳轉(zhuǎn)效果想必不是很常見吧,下面與大家分享下具體的實(shí)現(xiàn)另有實(shí)例,感興趣的朋友可以參考下哈2013-05-05
用JS實(shí)現(xiàn)HTML標(biāo)簽替換效果
用JS實(shí)現(xiàn)HTML標(biāo)簽替換效果...2007-06-06
javascript中apply和call方法的作用及區(qū)別說明
本篇文章主要是對javascript中apply和call方法的作用及區(qū)別進(jìn)行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助2014-02-02
微信小程序?qū)崙?zhàn)篇之購物車的實(shí)現(xiàn)代碼示例
本篇文章主要介紹了微信小程序?qū)崙?zhàn)篇之購物車的實(shí)現(xiàn)代碼示例,詳細(xì)的介紹了購物車的功能實(shí)現(xiàn),具有一定的參考價值,有興趣的可以了解一下2017-11-11

