ES新特性
1.概念
ES全程EcmaScript,是脚本语言的规范,Javascript是EcmaScript的一种实现,所以ES新特性就是指JavaScript的新特性。
1.1.编年史
年份 | 版本名称 | 正式名称 | 主要新增特性 | 重要事件/说明 |
---|---|---|---|---|
1997 | ECMAScript 1 | ES1 | 首个标准版本,定义了 JavaScript 的基础语法和功能。 | 由 ECMA 国际组织发布,对应 ECMA-262 标准第一版。 |
1998 | ECMAScript 2 | ES2 | 小幅更新,与 ISO/IEC 16262 标准同步。 | 修正规范格式,无重大功能新增。 |
1999 | ECMAScript 3 | ES3 | 正则表达式、try/catch 异常处理、instanceof 、typeof 、for...in 等。 | 成为 JavaScript 的通行标准,广泛支持,奠定了现代 JavaScript 的基础。 |
2007 | ECMAScript 4 | 未发布 | 模块、类、静态类型、泛型等激进特性(草案)。 | 草案因争议被终止,部分功能被拆分到后续版本。 |
2008 | ECMAScript 3.1 | ES5(重命名) | 基于 ES3 的小改进(如 JSON 支持、严格模式 use strict )。 | 原计划为 ES4 的子集,后更名为 ES5。 |
2009 | ECMAScript 5 | ES5 | 严格模式、JSON 支持、新对象方法(如 Object.create )、数组迭代方法等。 | 正式发布,成为主流浏览器支持的版本。 |
2011 | ECMAScript 5.1 | ES5.1 | 与 ISO/IEC 16262 国际标准同步,修正 ES5 的部分缺陷。 | 成为 ISO 国际标准(ISO/IEC 16262:2011)。 |
2013 | ECMAScript 6 草案 | ES6(草案冻结) | 类、模块、箭头函数、解构赋值、Promise 、模板字符串等。 | 草案冻结,不再添加新功能,进入讨论期。 |
2015 | ECMAScript 2015 | ES6 / ES2015 | 类、模块、箭头函数、解构赋值、let/const 、Promise 、模板字符串等。 | 正式发布,首次按年份命名(ES6 后改称 ES2015),是 JavaScript 的重大升级版本。 |
2016 | ECMAScript 2016 | ES7 / ES2016 | 指数运算符(** )、Array.prototype.includes() 。 | 首个年度版本,新增特性较少但保持持续更新。 |
2017 | ECMAScript 2017 | ES8 / ES2017 | Object.values() /keys() 、async/await 、for...of 与 let /const 支持。 | 引入 async/await 简化异步编程。 |
2018 | ECMAScript 2018 | ES9 / ES2018 | Promise.prototype.finally() 、async 函数的 iterable 支持、Rest/Spread 运算符。 | 增强异步编程和语法糖。 |
2019 | ECMAScript 2019 | ES10 / ES2019 | Array.prototype.flat() /flatMap() 、Object.fromEntries() 、String.trimStart()/trimEnd() 。 | 更多数组和字符串方法的优化。 |
2020 | ECMAScript 2020 | ES11 / ES2020 | Nullish 合并运算符(??) 、动态导入(import()) 、BigInt 、Promise.allSettled() 。 | 引入 BigInt 处理大整数,增强异步控制。 |
2021 | ECMAScript 2021 | ES12 / ES2021 | Logical Assignment Operators (&&= 、` |
2.ES6
2.1.迭代器
通过实现 Symbol.iterator
方法,可以自定义可迭代对象。
const customIterable = {
data: [10, 20, 30],
[Symbol.iterator]() {
let index = 0;
const data = this.data;
return {
next() {
if (index < data.length) {
return { value: data[index++], done: false };
} else {
return { done: true };
}
}
};
}
};
for (const num of customIterable) {
console.log(num); // 输出 10, 20, 30
}
2.2.生成器
生成器是一种特殊的函数,使用 function*
定义,通过 yield
关键字暂停和恢复执行,自动实现迭代器协议。
yield
会暂停函数执行,返回一个值给外部迭代器,下次调用next()
时从暂停处继续执行。
function* simpleGenerator() {
yield 1;
yield 2;
yield 3;
}
const gen = simpleGenerator();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.return(100)); // 提前终止,{ value: 100, done: true }
function* infiniteSequence() {
let i = 0;
while (true) {
yield i++;
}
}
const gen = infiniteSequence();
console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
// 无限继续...
function* fibonacci() {
let a = 0, b = 1;
while (true) {
yield a;
[a, b] = [b, a + b];
}
}
const fib = fibonacci();
console.log(fib.next().value); // 0
console.log(fib.next().value); // 1
console.log(fib.next().value); // 1
console.log(fib.next().value); // 2
2.3.Promise
Promise 是一个表示异步操作最终完成或失败的对象,代表了某个未来才会知道结果的事件(如网络请求、文件读写等)。
- 用途:处理异步操作(如网络请求、文件读取),避免回调地狱(Callback Hell)。
状态:
pending
(进行中):初始状态,既未成功也未失败。fulfilled
(已成功):操作成功完成,调用resolve
方法。rejected
(已失败):操作失败,调用reject
方法。
- 特点:状态一旦改变(如从
pending
到fulfilled
或rejected
),就不可逆,且后续操作只能通过then
或catch
处理结果。
2.3.1.创建Promise
通过 new Promise(executor)
构造函数创建:
const myPromise = new Promise((resolve, reject) => {
// 异步操作(如网络请求)
const success = true;
if (success) {
resolve("操作成功"); // 成功时调用 resolve
} else {
reject("操作失败"); // 失败时调用 reject
}
});
2.3.2.基础使用
then
:处理成功状态,接受两个参数(成功回调和失败回调):myPromise .then((value) => { console.log(value); // 输出 "操作成功" }, (error) => { console.error(error); });
catch
:专门处理失败状态,等同于.then(null, rejectCallback)
:myPromise .then((value) => console.log(value)) .catch((error) => console.error(error));
finally
方法:无论成功或失败,都会执行finally
回调(ES2018 引入):myPromise .then(data => console.log(data)) .catch(error => console.error(error)) .finally(() => console.log("操作完成"));
示例代码:
// 模拟异步请求
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
Math.random() > 0.5
? resolve("数据加载成功")
: reject("网络错误");
}, 1000);
});
}
// 使用示例
fetchData()
.then(data => console.log(data))
.catch(error => console.error(error))
.finally(() => console.log("请求结束"));
2.3.3.应用场景
网络请求:
fetch("https://api.example.com/data") .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error("请求失败", error));
文件读写:
const readFile = (path) => new Promise((resolve, reject) => { fs.readFile(path, (err, data) => { if (err) reject(err); else resolve(data); }); });
延时操作:
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms)); delay(1000).then(() => console.log("1秒后执行"));
2.3.4.高级用法
(1) Promise.all()
并行执行多个 Promise,全部成功后返回结果数组:
const promise1 = Promise.resolve(1);
const promise2 = new Promise((resolve) => setTimeout(() => resolve(2), 1000));
const promise3 = Promise.reject("错误");
Promise.all([promise1, promise2])
.then((results) => console.log(results)); // [1, 2]
Promise.all([promise1, promise2, promise3])
.catch((error) => console.error(error)); // "错误"
(2) Promise.race()
返回最先完成的 Promise 结果或错误:
const fastPromise = Promise.resolve("快");
const slowPromise = new Promise((resolve) => setTimeout(() => resolve("慢"), 2000));
Promise.race([fastPromise, slowPromise])
.then((result) => console.log(result)); // "快"
(3) Promise.allSettled()
(ES2020)
等待所有 Promise 完成(无论成功或失败):
const promises = [
Promise.resolve("成功"),
Promise.reject("失败"),
];
Promise.allSettled(promises).then((results) => {
results.forEach((result) => {
if (result.status === "fulfilled") {
console.log("成功:", result.value);
} else {
console.log("失败:", result.reason);
}
});
});
2.4.模块化
将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
2.4.1.语法
export
用于暴露规定模块的对外接口
import
用于引入外部的模块接口
示例
//util.js
export function isNull(){}
export function isNotNull(){}
//main.js
import * from "./utils.js"
import {isNUll, isNotNull} from "./utils.js"
import {isNUll} from "./utils.js"
- html中编写:
<script type="module"> import语句 </script
2.4.2.暴露方式
分别暴露
export let a = 1; export function isNull(){} export function isNotNull(){}
统一暴露
let a = ; function isNUll(){} export { a, isNull }
默认暴露
export default { name: "angsan" play: function (){ console.log("play basketball") } }
2.4.3.引入方式
- 通用方式:
import * as m1 from "./a.js"
- 解构赋值方式:
import {name as nickname, play} from "./a.js"
、import {default as m1} from "./a.js"
- 简单形式(针对默认暴露):
import m1 from "./a.js"
ES8
3.1.async&await
async: 声明一个异步函数,自动将函数返回值包装为 Promise
。
- 该函数返回一个
Promise
对象。 - 如果函数返回一个普通值(如
return 1
),则自动包装为Promise.resolve(值)
。 - 如果函数抛出异常(如
throw new Error
),则自动包装为Promise.reject(错误)
。
async function fetchData() {
// 异步操作(返回 Promise)
return "数据";
}
// 调用 async 函数
const result = fetchData(); // 返回 Promise
result.then(data => console.log(data)); // "数据"
await:暂停异步函数的执行,等待 Promise
完成并返回结果。
- 暂停当前
async
函数的执行,直到等待的Promise
完成(fulfilled
或rejected
)。 - 不会阻塞主线程,其他代码可以继续执行。
- 只能在
async
函数内部使用
async function getData() {
try {
const response = await fetch("https://api.example.com/data"); // 等待 Promise
const data = await response.json(); // 等待下一个 Promise
console.log(data);
} catch (error) {
console.error("错误:", error);
}
}
getData();
执行流程示例
async function asyncFunc() {
console.log("Start");
const result = await slowPromise(); // 暂停此处,等待Promise完成
console.log("Result:", result);
console.log("End");
}
asyncFunc();
console.log("Main code continues..."); // 立即执行,不阻塞主线程
function slowPromise() {
return new Promise(resolve => setTimeout(() => resolve("Done"), 1000));
}
应用示例:
//定义一个返回Promise对象的异步函数
function sendAJAX(url){
return new Promise(()=>{
const x = new XMLHttpRequest();
x.open('GET', url);
x.send();
x.onreadystatechange = function () {
if(x.readyState === 4){
if(x.status >= 200 && x.status < 300){
resolve(x.response)
}else{
reject(x.status)
}
}
}
});
}
sendAJAX("1").then(value=>console.log(value));
async function send(){
try{
let result = await sendAJAX("");
console.log(result);
}catch(error){
}
}
send();
ES11
可选链操作符
function readConfig(config){
const dbHost = config?.db?.host;
console.log(dbHost);//10.0.0.1
}
main({
db:{
host:'10.0.0.1',
username:'root'
},
cache:{
host:'10.0.0.1',
username:'admin'
}
});
动态import
//方法内部
import('./').then((module)=>{
module.hello();
});
globalThis
全局对象,