ES新特性

1.概念

ES全程EcmaScript,是脚本语言的规范,Javascript是EcmaScript的一种实现,所以ES新特性就是指JavaScript的新特性。

1.1.编年史

年份版本名称正式名称主要新增特性重要事件/说明
1997ECMAScript 1ES1首个标准版本,定义了 JavaScript 的基础语法和功能。由 ECMA 国际组织发布,对应 ECMA-262 标准第一版。
1998ECMAScript 2ES2小幅更新,与 ISO/IEC 16262 标准同步。修正规范格式,无重大功能新增。
1999ECMAScript 3ES3正则表达式、try/catch 异常处理、instanceoftypeoffor...in 等。成为 JavaScript 的通行标准,广泛支持,奠定了现代 JavaScript 的基础。
2007ECMAScript 4未发布模块、类、静态类型、泛型等激进特性(草案)。草案因争议被终止,部分功能被拆分到后续版本。
2008ECMAScript 3.1ES5(重命名)基于 ES3 的小改进(如 JSON 支持、严格模式 use strict)。原计划为 ES4 的子集,后更名为 ES5。
2009ECMAScript 5ES5严格模式、JSON 支持、新对象方法(如 Object.create)、数组迭代方法等。正式发布,成为主流浏览器支持的版本。
2011ECMAScript 5.1ES5.1与 ISO/IEC 16262 国际标准同步,修正 ES5 的部分缺陷。成为 ISO 国际标准(ISO/IEC 16262:2011)。
2013ECMAScript 6 草案ES6(草案冻结)类、模块、箭头函数、解构赋值、Promise、模板字符串等。草案冻结,不再添加新功能,进入讨论期。
2015ECMAScript 2015ES6 / ES2015类、模块、箭头函数、解构赋值、let/constPromise、模板字符串等。正式发布,首次按年份命名(ES6 后改称 ES2015),是 JavaScript 的重大升级版本。
2016ECMAScript 2016ES7 / ES2016指数运算符(**)、Array.prototype.includes()首个年度版本,新增特性较少但保持持续更新。
2017ECMAScript 2017ES8 / ES2017Object.values()/keys()async/awaitfor...oflet/const 支持。引入 async/await 简化异步编程。
2018ECMAScript 2018ES9 / ES2018Promise.prototype.finally()async 函数的 iterable 支持、Rest/Spread 运算符。增强异步编程和语法糖。
2019ECMAScript 2019ES10 / ES2019Array.prototype.flat()/flatMap()Object.fromEntries()String.trimStart()/trimEnd()更多数组和字符串方法的优化。
2020ECMAScript 2020ES11 / ES2020Nullish 合并运算符(??)动态导入(import())BigIntPromise.allSettled()引入 BigInt 处理大整数,增强异步控制。
2021ECMAScript 2021ES12 / ES2021Logical 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 方法。
  • 特点:状态一旦改变(如从 pendingfulfilledrejected),就不可逆,且后续操作只能通过 thencatch 处理结果。
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 完成(fulfilledrejected)。
  • 不会阻塞主线程,其他代码可以继续执行。
  • 只能在 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

全局对象,

最后修改:2025 年 05 月 11 日
如果觉得我的文章对你有用,请随意赞赏