一:ES8
1.尾随逗号
在ES8之前,尾随逗号会导致语法错误! ES8解决了这个问题
const colors = [
'red',
'blue',
'green',
'yellow', // 报错
];
const person = {
name: 'Tari Ibaba',
site: 'codingbeautydev.com', // 报错
}
2.async/await
不再需要烦人的then()嵌套
2.1 之前
wait().then(() => {
console.log('等待');
});
function wait() {
return new Promise((resolve) =>
setTimeout(resolve, 10 * 1000)
);
}
2.2 现在
// 💡 immediately invoked function expression (IIFE)
(async () => {
await wait();
console.log('等待');
})();
function wait() {
return new Promise((resolve) =>
setTimeout(resolve, 10 * 1000)
);
}
2.3 区别
// fetch 请求
// 之前
function getSuggestion() {
fetch('https://api.example/suggestion')
.then((res) => {
return res.json();
})
.then((data) => {
const { suggestion } = data;
console.log(suggestion);
});
}
//现在
async function getSuggestion() {
const res = await fetch('https://api.example/suggestion');
const { suggestion } = await res.json();
console.log(suggestion);
}
2.4 使用async/await,使用原生的 try-catch
startWorkout();
// async/await
async function startWorkout() {
try {
await goToGym();
} catch (err) {
console.log(err);
}
}
function goToGym() {
return new Promise((resolve, reject) => {
if (Math.random() > 0.5) {
reject(new Error("错误"));
}
resolve("正确");
});
}
3. Object静态方法
3.1 Object.values() Object.keys()
const person = {
name: 'Ibaba',
site: 'com',
color: 'blue',
};
const arr = Object.values(person);
const arr1 = Object.keys(person);
// ['Ibaba', 'com', 'blue']
// ['name', 'site', 'color']
console.log(arr,arr1);
3.2 Object.entries()
const person = {
name: 'Tari Ibaba',
site: 'codingbeautydev.com',
color: 'blue',
};
const arr = Object.entries(person);
/*
[
['name', 'Tari Ibaba'],
['site', 'codingbeautydev.com'],
['color', 'blue']
]
*/
console.log(arr);
3.3 以ID为键的对象 → 对象列表
const tasks = {
1: {
title: 'HIIT 30 minutes today',
complete: false,
},
2: {
name: 'Buy the backpack',
complete: true,
},
};
const taskList = Object.keys(tasks).map((id) => ({
id,
...tasks[id],
}));
console.log(taskList);
4. padStart
const name = 'tari'
// 10 : 要达到的字符串长度,必须为一个正整数 🦬 可选的填充字符串,如果不指定,则默认为一个空格
console.log(name.padStart(10, '🦬')); // '🦬🦬🦬tari'
console.log(name.padEnd(10, '🦬')); // 'tari🦬🦬🦬'
5. Object.getOwnPropertyDescriptors()
返回一个对象,该对象描述给定对象上特定属性(即直接存在于对象上而不在对象的原型链中的属性)的配置。返回的对象是可变的,但对其进行更改不会影响原始属性的配置
value:与属性关联的值(仅限数据描述符)。
writable:当且仅当与属性关联的值可以更改时,为 true(仅限数据描述符)。简单可以理解为该属性是否可以被重写。
enumerable:当且仅当此属性在相应对象的属性枚举中出现时,为 true。简单理解为可以被遍历
confiruable:当且仅当此属性描述符的类型可以更改且该属性可以从相应对象中删除时,为 true。是否可以被再配置。
5.1 实例
const obj = {
foo: 123,
bar: 456
};
const propertyDescriptors = Object.getOwnPropertyDescriptors(obj);
console.log(propertyDescriptors);
// {
// foo: { value: 123, writable: true, enumerable: true, configurable: true },
// bar: { value: 456, writable: true, enumerable: true, configurable: true }
// }
二:ES9
1:异步生成器和迭代
1.1 普通生成器
function* asyncGenerator() {
yield new Promise((resolve) =>
setTimeout(() => resolve('done this ✅'), 2000)
);
yield new Promise((resolve) =>
setTimeout(() => resolve('done that ✅'), 3000)
);
}
// 当我们调用.next()时,我们会得到一个Promise
const asyncGen = asyncGenerator();
asyncGen.next().value.then(console.log);
asyncGen.next().value.then(console.log);
1.2 利用生成器写一个视频流
async function* streamVideo({ id }) {
let endOfVideo = false;
const downloadChunk = async (sizeInBytes) => {
const response = await fetch(
`api.example.com/videos/${id}`
);
const { chunk, done } = await response.json();
if (done) endOfVideo = true;
return chunk;
};
while (!endOfVideo) {
const bufferSize = 500 * 1024 * 1024;
yield await downloadChunk(bufferSize);
}
}
// 用for await of — 异步迭代
for await (const chunk of streamVideo({ id: 2341 })) {
// process video chunk
}
2:对象的剩余/展开运算符
let arr = [1, 2, 3];
let arr1 = [...arr, 4]
console.log(arr1); // [1, 2, 3, 4]
let obj = { a: 1, b: 2 }
let obj1 = { ...obj, c: 3 }
console.log(obj1);// { a: 1, b: 2, c: 3 }
3:Promise.finally
3.1 finally总是会运行一些代码,无论是否有错误
function startBodyBuilding() {
if (Math.random() > 0.5) {
throw new Error("I'm tired😩");
}
console.log('Off to the gym 🏋️♂️💪');
}
try {
startBodyBuilding();
} catch {
console.log('Stopped excuse🛑');
} finally {
console.log("I'm going!🏃♂️");
}
3.2 异步任务
async function startBodyBuilding() {
await think();
if (Math.random() > 0.5) {
throw new Error("I'm tired😩");
}
console.log('Off to the gym 🏋️♂️💪');
}
startBodyBuilding()
.then(() => {
console.log('Started ✅');
})
.catch(() => {
console.log('No excuses');
})
.finally(() => {
console.log("I'm going!🏃♂️");
});
3.3:链接许多Promise
getFruitApiUrl().then((url) => {
return fetch(url)
.then((res) => res.json())
.then((data) => {
fruits.push(data);
})
.catch((err) => {
console.error(err);
})
.finally(() => {
console.log(fruits);
});
});
三:ES10
1.flat()和flatMap()提供了更清晰的方式来轻松扁平化多维数组
const animal = [ 'cat','dog','pig',['vegetableChicken','turkey'],['duck',['lettleDuck','bigDuck']]]
console.log(animal.flat(1))
// [ 'cat','dog','pig','vegetableChicken','turkey','duck',['lettleDuck','bigDuck']]
console.log(animal.flat(2));
//[ 'cat','dog','pig','vegetableChicken','turkey','duck','lettleDuck','bigDuck']
const arr1 = [1, 2, 3, 4, 5];
const n1 = arr1.flatMap((x) => [x ** 2]);
console.log(n1); // [1, 4, 9, 16, 25]
const n2 = arr1.map((x) => [x ** 2]);
console.log(n2); // [[1],[4],[9],[16],[25]]
console.log(n2.flat()); // [1, 4, 9, 16, 25]
2. 将数组转换为对象 bject.fromEntries()
//快速将键值对列表转换为等效的键值对象
const entries = [['name', 'John'], ['age', 30]];
const obj = Object.fromEntries(entries);
console.log(obj); // { name: 'John', age: 30 }
3.精确清理你的字符串 trimStart()和trimEnd()
const str = ' Hello, World! ';
console.log(str.trimStart()); // 'Hello, World! '
console.log(str.trimEnd()); // ' Hello, World!'
4. 捕获错误而不带包袱 通过新的可选catch绑定,当你对错误参数无所作为时,现在可以安全地省略catch块的错误参数
5.BigInt 大整数
// 创建大整数得方法
//1.n 结尾
let num = 1234222222223242121n + 233333333333333n
// 1234455555556575454n
// 2.BigInt()
let num1 = BigInt(12222222222222222222) + BigInt(23333333333333333333)
// 35555555555555553280n
BigInt 只能和 BigInt 做运算 否则报错
ES13
1.顶级await
在ES13之前,我们永远不能在全局作用域中使用await
之前
// X 语法错误:await 只在异步函数中有效
await setTimeoutAsync(3000);
function setTimeoutAsync(timeout) {
return new Promise((resolve) => {
setTimeout(() => {
resolve('codingbeautydev.com');
}, timeout);
});
}
// 我们总是必须将其放在async函数中或创建一个async IIFE(立即执行函数表达式)
// 异步立即执行函数
(async () => {
await setTimeoutAsync(3000);
})();
// 类似 C++
async function main() {
await setTimeoutAsync(3000);
}
现在
await setTimeoutAsync(3000);
function setTimeoutAsync(timeout) {
return new Promise((resolve) => {
setTimeout(() => {
resolve('codingbeautydev.com');
}, timeout);
});
}
2.数组升级:新的at()方法
通常我们会使用方括号([])来访问数组的第N个元素
const arr = ['a', 'b', 'c', 'd'];
console.log(arr[1]); // b
但从末尾访问第N个项目一直是一个痛点 – 我们必须使用arr.length - N进行索引
const arr = ['a', 'b', 'c', 'd'];
// 倒数第1个元素
console.log(arr[arr.length - 1]); // d
// 倒数第2个元素
console.log(arr[arr.length - 2]); // c
现在
const str = 'Coding Beauty';
console.log(str.at(-1)); // y 倒数第1个字符
console.log(str.at(-2)); // t 倒数第2个字符
4.错误报告升级
// 有时我们捕获调用栈下方方法的错误,只是为了将其重新抛出回调用栈上方。 但当我们这样做时,我们会失去原始错误中的关键信息
try {
userAction();
} catch (err) {
// ❌ doesn't know fundamental cause of error
// ❌ 不知道错误的根本原因
console.log(err);
}
function userAction() {
try {
apiCallThatCanThrow();
} catch (err) {
// 👇 rethrow
// 👇 重新抛出错误
throw new Error('New error message');
}
}
function apiCallThatCanThrow() {
console.log('fetching from codingbeautydev.com...');
throw new Error('throwing for no reason');
}
现在
try {
userAction();
} catch (err) {
// ✅ now knows what caused the error
// ✅ 现在知道了错误的原因
console.log(err);
console.log(`Caused by: ${err.cause}`);
}
function userAction() {
try {
apiCallThatCanThrow();
} catch (err) {
// ✅ error cause
// ✅ 错误原因
throw new Error('New error message', { cause: err });
}
}
function apiCallThatCanThrow() {
console.log('fetching from codingbeautydev.com...');
throw new Error('throwing for no reason');
}
ES14
1. toSorted()
ES14的toSorted()方法使得排序数组并返回一个副本而不改变原数组变得更加容易
之前
const numbers = [3, 1, 4, 1, 5];
const sorted = [...numbers].sort((a, b) => a - b);
console.log(sorted); // [1, 1, 3, 4, 5]
console.log(numbers); // [3, 1, 4, 1, 5]
现在
const numbers = [3, 1, 4, 1, 5];
const sorted = numbers.toSorted((a, b) => a - b);
console.log(sorted); // [1, 1, 3, 4, 5]
console.log(numbers); // [3, 1, 4, 1, 5]
toSorted()接受一个回调函数来控制排序行为 - 升序或降序,按字母顺序或数字顺序。就像sort()一样。
2. toReversed() 用于促进不可变性和函数式编程
之前
const numbers = [1, 2, 3, 4, 5];
const reversed = numbers.reverse();
console.log(reversed); // [5, 4, 3, 2, 1]
console.log(numbers); // [5, 4, 3, 2, 1] // 改变原数组
现在
const numbers = [1, 2, 3, 4, 5];
const reversed = numbers.toReversed();
console.log(reversed); // [5, 4, 3, 2, 1]
console.log(numbers); // [1, 2, 3, 4, 5]
同时支持
const result = numbers.toReversed().toSorted((a, b) => a - b); //链式调用
3. toSpliced() 这是.splice()的不可变版本
const items = [1, 2, 3, 4, 5];
const newItems = items.toSpliced(2, 1, 6, 7); //删除位置 删除个数 插入数据
console.log(newItems); // [1, 2, 6, 7, 4, 5]
console.log(items); // [1, 2, 3, 4, 5]
4. 数组的with()方法 是我们快速更改数组元素而不进行任何突变的方法
之前
const arr = [1, 2, 3, 4, 5];
const newArr = [...arr];
newArr[2] = 6;
console.log(newArr); // [1, 2, 6, 4, 5]
console.log(arr); // [1, 2, 3, 4, 5]
现在
const arr = [1, 2, 3, 4, 5];
const newArr = arr.with(2, 6);
console.log(newArr); // [1, 2, 6, 4, 5]
console.log(arr); // [1, 2, 3, 4, 5]