從ES7到ES12,了解JavaScript的新特性與語法演變
??ES2016(ES7):
一、Array.prototype.includes
1.1 定義
Array.prototype.includes 是一個用于判斷數(shù)組是否包含特定元素的方法。它返回一個布爾值,表示數(shù)組中是否存在指定的值。
1.2 語法
arr.includes(searchElement[, fromIndex])
-
arr: 要調(diào)用includes方法的數(shù)組。 -
searchElement: 要查找的元素。 -
fromIndex(可選): 開始查找的索引位置。如果省略該參數(shù),則從數(shù)組的開頭(索引 0)開始查找。如果fromIndex為負(fù)數(shù),則從數(shù)組的末尾開始計算。
1.3 返回值
一個布爾值。如果數(shù)組包含指定的元素,則返回 true,否則返回 false。
1.4 舉例
const numbers = [1, 2, 3, 4, 5];
console.log(numbers.includes(3)); // true
console.log(numbers.includes(6)); // false
console.log(numbers.includes(3, 2)); // false,從索引 2 開始查找
二、Exponentiation Operator 指數(shù)運算符
2.1 定義
Exponentiation Operator 是一個用于進(jìn)行指數(shù)運算的運算符,它允許將一個數(shù)值(底數(shù))進(jìn)行指定次數(shù)的乘方運算。
2.2 語法
base ** exponent
-
base: 底數(shù),即要進(jìn)行乘方運算的數(shù)值。 -
exponent: 指數(shù),表示要將底數(shù)乘方的次數(shù)。
2.3 舉例
console.log(2 ** 3); // 2的3次方,輸出: 8
console.log(5 ** 2); // 5的2次方,輸出: 25
console.log(10 ** 0); // 任何數(shù)的0次方都為1,輸出: 1
Exponentiation Operator 提供了一種簡潔的語法來進(jìn)行乘方運算,避免了使用 Math.pow 等其他方法。
??ES2017(ES8):
一、Async functions
1.1 定義
Async functions 是 async 聲明的函數(shù),async 函數(shù)是 AsyncFunction 構(gòu)造函數(shù)的實例,其中允許使用 await 關(guān)鍵字。
1.2 語法
async function name([param[, param[, ...param]]]) {
// statements
}
1.3 返回值
一個 Promise
1.4 示例:
async function fetchData() {
try {
console.log('Fetching data...');
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log('Data fetched successfully:', data);
return data;
} catch (error) {
console.error('Error fetching data:', error);
throw error;
}
}
fetchData();
二、Object.entries
2.1 返回值
Object.entries() 方法返回一個給定對象自身可枚舉屬性的鍵值對數(shù)組。
2.2 語法
Object.entries(obj);
2.3 示例
const obj = { a: 1, b: 2 };
const entries = Object.entries(obj);
console.log(entries); // 輸出:[['a', 1], ['b', 2]]
三、Object.values
3.1 返回值
Object.values()方法返回一個給定對象自身可枚舉屬性值的數(shù)組。
3.2 語法
Object.values(obj);
3.3 示例
const obj = { a: 1, b: 2 };
const values = Object.values(obj);
console.log(values); // 輸出:[1, 2]
四、Object.getOwnPropertyDescriptors
4.1 返回值
Object.getOwnPropertyDescriptors() 方法用來獲取一個對象的所有自身屬性的描述符。
4.2 語法
Object.getOwnPropertyDescriptors(obj);
4.3 示例
const obj = { a: 1, b: 2 };
const descriptors = Object.getOwnPropertyDescriptors(obj);
console.log(descriptors);
// 輸出:
// {
// a: { value: 1, writable: true, enumerable: true, configurable: true },
// b: { value: 2, writable: true, enumerable: true, configurable: true }
// }
五、Trailing commas 尾后逗號
5.1 定義
如果你想要添加新的屬性,并且在上一行已經(jīng)使用了尾后逗號,你可以僅僅添加新的一行,而不需要修改上一行。
5.2 示例
// 數(shù)組
const arr = [
1,
2,
];
// 對象
const obj = {
a: 1,
b: 2,
};
// 函數(shù)參數(shù)定義
function sum(x, y,) {
return x + y;
}
// 函數(shù)調(diào)用
console.log(sum(1, 2)); // 輸出:3
六、String.prototype.padStart()
6.1 定義
padStart() 用另一個字符串填充當(dāng)前字符串。
6.2 返回值
在原字符串開頭填充指定的填充字符串直到目標(biāo)長度所形成的新字符串。
6.3 語法
str.padStart(targetLength);
str.padStart(targetLength, padString);
6.4 示例
const str = 'abc';
const paddedStr = str.padStart(10);
console.log(paddedStr); // 輸出:" abc"
七、String.prototype.padEnd()
7.1 定義
padEnd() 方法會用一個字符串填充當(dāng)前字符串(如果需要的話則重復(fù)填充)。
7.2 返回值
返回在原字符串末尾填充指定的填充字符串直到目標(biāo)長度所形成的新字符串。
7.3 語法
str.padEnd(targetLength);
str.padEnd(targetLength, padString);
7.4 示例
const str = 'abc';
const paddedStr = str.padEnd(10);
console.log(paddedStr); // 輸出:"abc "
??ES2018(ES9):
一、Async iterators 異步迭代器
1.1 定義
異步迭代器是在 ES2018 中引入的一種新的迭代器類型。它允許在進(jìn)行迭代時異步地獲取序列的下一個值。
1.2 異步迭代器協(xié)議
異步迭代器對象必須實現(xiàn)一個名為 Symbol.asyncIterator 的方法,該方法返回一個異步迭代器對象。
異步迭代器對象應(yīng)該實現(xiàn)一個名為 next 的異步方法,該方法返回一個 Promise,解析為一個包含 value 和 done 屬性的對象。
-
value:表示迭代器返回的值。 -
done:一個布爾值,表示迭代器是否已完成迭代。
1.3 舉例
// 異步迭代器示例
const asyncIterable = {
[Symbol.asyncIterator]() {
let i = 0;
return {
async next() {
if (i < 3) {
await new Promise((resolve) => setTimeout(resolve, 1000));
return { value: i++, done: false };
} else {
return { done: true };
}
},
};
},
};
// 異步迭代
(async function () {
for await (const num of asyncIterable) {
console.log(num);
}
})();
二、Object rest properties 剩余屬性
2.1 定義
Object rest properties 允許使用剩余語法來獲取除已解構(gòu)屬性之外的其余屬性,并將它們放置在一個新的對象中。
2.2 語法
const { prop1, prop2, ...rest } = object;
2.3 舉例
const person = { name: 'John', age: 30, city: 'New York', country: 'USA' };
const { name, age, ...address } = person;
console.log(name); // 'John'
console.log(age); // 30
console.log(address); // { city: 'New York', country: 'USA' }
三、Object spread properties 擴展屬性
3.1 定義
Object spread properties 允許使用擴展運算符將一個對象的所有屬性拷貝到另一個對象中。
3.2 語法
const newObj = { ...obj };
3.3 舉例
const defaults = { option1: true, option2: false };
const userConfig = { option2: true };
const finalConfig = { ...defaults, ...userConfig };
console.log(finalConfig);
// Output: { option1: true, option2: true }
四、Promise.prototype.finally
4.1 定義
Promise.prototype.finally 方法允許你在 Promise 完成時,無論結(jié)果是成功還是失敗,都執(zhí)行一些代碼。
4.2 語法
promise.finally(onFinally);
-
onFinally: 一個在 Promise 完成時執(zhí)行的函數(shù)。
4.3 返回值
一個新的 Promise,由原始 Promise 完成時的值或原始錯誤傳遞。
4.4 舉例
function fetchData() {
return new Promise((resolve, reject) => {
// 模擬異步操作
setTimeout(() => {
const data = Math.random();
data > 0.5 ? resolve(data) : reject('Error: Data too small');
}, 1000);
});
}
fetchData()
.then((result) => console.log('Success:', result))
.catch((error) => console.error('Error:', error))
.finally(() => console.log('Finally: Cleanup or Final Tasks'));
??ES2019(ES10):
一、Array.prototype.{flat, flatMap} 扁平化嵌套數(shù)組
1.1 Array.prototype.flat
1.1.1 定義
flat() 方法會按照一個可指定的深度遍歷遞歸數(shù)組,并將所有元素與遍歷到的子數(shù)組中的元素合并為一個新數(shù)組返回。
1.1.2 語法
arr.flat([depth]);
-
depth是數(shù)組遍歷的深度,默認(rèn)是 1。
1.1.3 返回值
一個新數(shù)組,不會改變舊數(shù)組。
1.1.4 舉例
const arr = [1, 2, [[[3, 4]]]];
arr.flat(); // [1, 2, [[[3, 4]]]]
arr.flat(3); // [1, 2, [3, 4]]
arr.flat(-1); // [1, 2, [[[3, 4]]]]
arr.flat(Infinity); // [1, 2, 3, 4]
1.1.5 注意
flat() 會移除數(shù)組中的空項。
let arr = [1, 2, , , 3];
arr.flat(); // [1, 2, 3]
1.1.6 替換
-
reduce與concat
let arr = [1, 2, [3, 4]];
arr.reduce((arr, val) => arr.concat(val), []);
- 擴展運算符與
concat
let arr = [1, 2, [3, 4]];
[].concat(...arr);
1.2 Array.prototype.flatMap
1.2.1 定義
flatMap() 方法首先使用映射函數(shù)映射數(shù)組(深度值為 1)的每個元素,然后將結(jié)果壓縮成一個新數(shù)組。
1.2.2 返回值
一個新數(shù)組,并且每個元素都是回調(diào)函數(shù)的結(jié)果。
1.2.3 語法
arr.flatMap(function callback(currentVal[, index[, array]]) {
}[, thisArg])
-
callback: 可以生成一個新數(shù)組所調(diào)用的函數(shù)-
currentVal: 當(dāng)前數(shù)組在處理的元素 -
index: 可選,正在處理的元素索引 -
array: 可選,被調(diào)用的數(shù)組
-
-
thisArg: 執(zhí)行 callback 函數(shù)時使用的 this 值
1.2.4 舉例
let arr = ['My name', 'is', '', 'Lisa'];
let newArr1 = arr.flatMap(cur => cur.split(' '));
let newArr2 = arr.map(cur => cur.split(' '));
console.log(newArr1); // ["My", "name", "is", "", "Lisa"]
console.log(newArr2); // [["My", "name"], ["is"], [""], ["Lisa"]]
二、Object.fromEntries
2.1 定義
fromEntries() 方法會把鍵值對列表轉(zhuǎn)換成一個對象。
2.2 返回值
一個新的對象。
2.3 語法
Object.fromEntries(iterable)
-
iterable: Array、Map 等可迭代對象
2.4 舉例
let map = new Map([['a', 1], ['b', 2]]);
let mapToObj = Object.fromEntries(map);
console.log(mapToObj); // {a: 1, b: 2}
let arr = [['a', 1], ['b', 2]];
let arrToObj = Object.fromEntries(arr);
console.log(arrToObj); // {a: 1, b: 2}
let obj = {a: 1, b: 2};
let newObj = Object.fromEntries(
Object.entries(obj).map(
([key, val]) => [key, val * 2]
)
);
console.log(newObj); // {a: 2, b: 4}
三、String.prototype.{trimStart, trimEnd}
3.1 String.prototype.trimStart
3.1.1 定義
trimStart() 方法用來刪除字符串的開頭的空白字符。
trimLeft() 是它的別名。
3.1.2 返回值
一個新的字符串,這個字符串左邊的空格已經(jīng)被去除掉了。
3.1.3 語法
str.trimStart();
str.trimLeft();
3.1.4 ?? 舉例
let str = ' a b cd ';
str.trimStart(); // 'a b cd '
str.trimLeft(); // 'a b cd '
3.2 String.prototype.trimEnd
3.2.1 定義
trimEnd() 方法用來刪除字符串末尾的空白字符。trimRight() 是它的別名。
3.2.2 返回值
一個新的字符串,這個字符串右邊的空格已經(jīng)被去除了。
3.2.3 語法
str.trim
End();
str.trimRight();
3.2.4 ?? 舉例
let str = ' a b cd ';
str.trimEnd(); // ' a b cd'
str.trimRight(); // ' a b cd'
四、Symbol.prototype.description
4.1 定義
description 是一個只讀屬性,返回 Symbol 對象的可選描述符。
4.2 語法
Symbol.prototype.description
4.3 返回值
一個可選的字符串描述符。
4.4 ?? 舉例
const sym = Symbol('This is my symbol');
console.log(sym.description); // "This is my symbol"
五、Optional catch binding
5.1 定義
ES10 引入了可選的 catch 綁定,允許在 catch 塊中省略異常參數(shù)。
5.2 語法
try {
// 代碼塊
} catch {
// 異常處理
}
5.3 舉例
try {
// 可能出現(xiàn)異常的代碼
} catch {
// 不需要異常參數(shù)了,直接處理異常
}
六、Array.prototype.sort()
6.1 定義
在 ES10 中,規(guī)范明確了 Array.prototype.sort() 方法必須使用穩(wěn)定排序算法。在先前的規(guī)范中,對于沒有指定排序算法的瀏覽器和引擎,可能使用不穩(wěn)定的排序算法。穩(wěn)定排序算法會保持相等元素的原始相對順序。
6.2 示例
const arr = [{ num: 2 }, { num: 1 }, { num: 2 }, { num: 3 }];
arr.sort((a, b) => a.num - b.num);
console.log(arr);
// Output: [{ num: 1 }, { num: 2 }, { num: 2 }, { num: 3 }]
??ES10(ES2019):
一、空值合并運算符(Nullish coalescing Operator)
1.1 定義
空值合并運算符(??)是一個邏輯操作符,用于在變量為 null 或 undefined 時,提供一個默認(rèn)值。
1.2 語法
const result = valueToCheck ?? defaultValue;
1.3 示例
const name = null;
const defaultName = 'John Doe';
const result = name ?? defaultName;
console.log(result); // Output: "John Doe"
const age = 0;
const defaultAge = 18;
const result2 = age ?? defaultAge;
console.log(result2); // Output: 0
二、可選鏈 Optional chaining
2.1 定義
可選鏈操作符(?.)允許在對象鏈中安全地訪問深層的屬性或方法,當(dāng)遇到 null 或 undefined 時不會拋出錯誤,而是返回 undefined。
2.2 語法
const result = object?.property?.nestedProperty;
2.3 示例
const person = {
name: 'John Doe',
address: {
city: 'New York',
},
};
const cityName = person?.address?.city;
console.log(cityName); // Output: "New York"
const age = person?.age;
console.log(age); // Output: undefined
三、globalThis
3.1 定義
globalThis 是一個全局對象的標(biāo)準(zhǔn)屬性,用于在任何環(huán)境中獲取全局對象,無論在瀏覽器、Web Workers、Node.js 還是其他環(huán)境中。
3.2 使用場景
在不同的環(huán)境中,獲取全局對象有不同的方式:
- 在瀏覽器中可以使用
window或self - 在 Web Workers 中可以使用
self或globalThis - 在 Node.js 中可以使用
global
現(xiàn)在,可以統(tǒng)一使用 globalThis 來獲取全局對象,無需關(guān)心當(dāng)前運行環(huán)境。
3.3 示例
在瀏覽器中:
console.log(globalThis === window); // true
console.log(globalThis === self); // true
在 Node.js 中:
console.log(globalThis === global); // true
在 Web Workers 中:
console.log(globalThis === self); // true
四、BigInt
4.1 定義
BigInt 是一種內(nèi)置對象,用于表示任意大的整數(shù)。
4.2 創(chuàng)建 BigInt
BigInt 可以通過在整數(shù)字面量后面加 n 來創(chuàng)建。
const bigIntNumber = 9007199254740991n;
或者調(diào)用函數(shù) BigInt() 并傳遞一個整數(shù)值或字符串值。
const bigIntNumber2 = BigInt(9007199254740991);
const bigIntNumber3 = BigInt('9007199254740991');
4.3 示例
const a = 9007199254740991n;
const b = BigInt('9007199254740991');
const c = BigInt(9007199254740991);
console.log(a); // Output: 9007199254740991n
console.log(b); // Output: 9007199254740991n
console.log(c); // Output: 9007199254740991n
console.log(typeof a); // Output: "bigint"
五、String.prototype.matchAll()
5.1 定義
matchAll() 方法返回一個包含正則表達(dá)式全局匹配結(jié)果的迭代器。
5.2 語法
const iterator = string.matchAll(regexp);
5.3 示例
const str = 'test1test2';
const regexp = /t(e)(st(\d?))/g;
const matches = [...str.matchAll(regexp)];
for (const match of matches) {
console.log(match);
}
六、Promise.allSettled()
6.1 定義
Promise.allSettled() 方法返回一個在所有給定的 promise 都已經(jīng) fulfilled 或 rejected 后的 promise,并帶有一個對象數(shù)組,每個對象表示對應(yīng)的 promise 結(jié)果。
6.2 語法
const promises = [promise1, promise2, ...];
Promise.allSettled(promises)
.then(results => {
// Handle results
})
.catch(error => {
// Handle error
});
6.3 示例
const promise1 = Promise.resolve(1);
const promise2 = Promise.reject(new Error('Error occurred'));
Promise.allSettled([promise1, promise2])
.then(results => {
console.log(results);
})
.catch(error => {
console.error(error);
});
七、Dynamic import(按需 import)
7.1 定義
Dynamic import 是一種動態(tài)導(dǎo)入模塊的方法,它可以在需要的時候才加載模塊,而不是在代碼運行時一開始就加載。
7.2 語法
import(modulePath)
.then(module => {
// Use module
})
.catch(error => {
// Handle error
});
7.3 示例
button.addEventListener('click', event => {
import('./test.js')
.then(test => {
alogBox.open();
})
.catch(error => {
// Handle error
});
});
八、Promise.any
8.1 定義
Promise.any() 方法接受一組 Promise 實例作為參數(shù),并返回一個新的 Promise 實例。該 Promise 實例在參數(shù)中的任意一個 Promise 成功(fulfilled)時變?yōu)?fulfilled 狀態(tài),如果所有參數(shù)實例都變成 rejected 狀態(tài),則返回一個 AggregateError 類型的實例,包含所有錯誤信息。
8.2 語法
Promise.any([promise1, promise2, ...])
.
then(result => {
// Handle the first fulfilled result
})
.catch(errors => {
// Handle errors
});
8.3 示例
const promise1 = new Promise((resolve, reject) => setTimeout(reject, 500, 'Error 1'));
const promise2 = new Promise(resolve => setTimeout(resolve, 300, 'Result 2'));
const promise3 = new Promise(resolve => setTimeout(resolve, 800, 'Result 3'));
Promise.any([promise1, promise2, promise3])
.then(result => {
console.log(result); // Output: "Result 2"
})
.catch(errors => {
console.error(errors); // Output: AggregateError: All promises were rejected
});
??ES2021(ES12):
一、邏輯運算符和賦值表達(dá)式
1.1 定義
ES12 引入了邏輯運算符和賦值表達(dá)式的組合,這些運算符方便地對變量進(jìn)行條件賦值操作。
1.2 語法
-
&&=:邏輯與賦值表達(dá)式,將右側(cè)的值賦給左側(cè)的變量,但僅當(dāng)左側(cè)的變量在布爾上下文中為真時。 -
||=:邏輯或賦值表達(dá)式,將右側(cè)的值賦給左側(cè)的變量,但僅當(dāng)左側(cè)的變量在布爾上下文中為假時。 -
??=:空值合并賦值表達(dá)式,將右側(cè)的值賦給左側(cè)的變量,但僅當(dāng)左側(cè)的變量為 null 或 undefined 時。
1.3 示例
let x = 5;
let y = 10;
// 邏輯與賦值表達(dá)式
x &&= y;
console.log(x); // Output: 10 (因為 x 為真,所以將 y 賦給 x)
let a = 0;
let b = 20;
// 邏輯或賦值表達(dá)式
a ||= b;
console.log(a); // Output: 20 (因為 a 為假,所以將 b 賦給 a)
let foo = null;
let bar = 'Hello';
// 空值合并賦值表達(dá)式
foo ??= bar;
console.log(foo); // Output: "Hello" (因為 foo 為 null,所以將 bar 賦給 foo)
二、String.prototype.replaceAll()
2.1 定義
String.prototype.replaceAll() 方法用于替換字符串中所有匹配的子字符串,類似于 String.prototype.replace(),但是會替換所有匹配,而不僅僅是第一個匹配。
2.2 語法
const newStr = originalStr.replaceAll(searchValue, replaceValue);
2.3 示例
const str = 'Hello, hello, hello';
const newStr = str.replaceAll('hello', 'Hi');
console.log(newStr); // Output: "Hello, Hi, Hi"
三、數(shù)字分隔符
3.1 定義
數(shù)字分隔符是一種增強的數(shù)值表示法,可以在數(shù)字中使用下劃線 _ 進(jìn)行分隔,以提高數(shù)字的可讀性。
3.2 示例
const billion = 1_000_000_000;
const pi = 3.14_15_92_65;
console.log(billion); // Output: 1000000000
console.log(pi); // Output: 3.14159265
