Es6-Es13使用方法及特性(万字超详细)

目录

 ES6

let

const

解构赋值

模板字符串

 字符串与数值的扩展

数组的扩展

对象的扩展

函数的扩展

Symbol 类型

iterator 迭代器

Set数据结构

Map数据结构

Proxy代理

Reflect反射

Promise对象

Generator生成器函数

class语法

class继承

ES7

求幂运算符

 数组的includes方法

ES8

async和await

对象方法扩展

字符串填充

ES9

rest与扩展运算符

正则命名捕获分组

Promise.finally

异步迭代

ES10

Object.fromEntries

 trimStart和trimEnd

flat()和flatMap() 

 symbol.description 

ES11

Promise.allSettled

Module新增

字符串的matchAll方法

bigint (大整数)类型

globalThis 顶层对象

空值合并运算符 ??

可选链操作符 ?.

ES12

新增逻辑操作符

字符串的replaceAll 方法

Promise.any

WeakRef

ES13

类新增特性

顶层 await 

at函数

findLast 和 findLastIndex

catch捕获错误添加原因


 ES6

let

      // 块级作用域
      // 不允许重复声明
      // 没有变量提升

      // 暂存性死区
      let name = "纳西妲";
      function fn() {
        console.log(name);
        let name =
          "局部作用域里调用之后再用let声明变量,就会出现暂存性死区,会报错";
      }
      fn();

      // 不与顶层对象挂钩
      var names = "挂载在window上";
      console.log(window.names); // 挂载在window上

      let notMsg = "不关联";
      console.log(window.notMsg); // undefined

const

      // 常量
      // 不能重复定义
      // 有块级特性
      // 也有暂存性死区特点
      // 也不与顶层对象挂钩
      const name = 1;

      // 当一个常量为复杂数据类型,是可以改变其属性的
      const obj = Object.freeze({
        name: "张三",
        age: 18,
        child: {
          name: "冻不住",
        },
      });
      // 可以使用冻结方法,让常量不可更改(只能冻住一层)

解构赋值

      // 数组解构
      let arr = [1, 2, 3];
      let [a, b, c] = arr; // 1,2,3
      let [d, [e, f], g] = [1, [2, 3], 5]; // 1,2,3,5
      let [x = 999] = []; // 999
      let [y = 999] = [666]; // 666
      console.log(y);

      // 对象解构
      const obj = {
        name: "张三",
        age: 18,
        child: { list: [6, 7, 8] },
      };

      let {
        name,
        age,
        child: { list },
      } = obj;
      console.log(name, age, list);

      // 字符串解构
      let { length } = "nan";
      console.log(length); // 3

模板字符串

// ${} 大括号里面可以放表达式或变量作为字符串

 字符串与数值的扩展

      let myName = "jack";
      myName.includes("a", 1); // true 判断字符串是否包含某个字符

      myName.startsWith("j", 0); // true 以...开始

      myName.endsWith("j", 1); // true 以...结尾

      myName.repeat(3); // jackjackjack 重复三次

      Number.isFinite("100"); // false 判断数字是否合法,没有隐式转换

      Number.isNaN(NaN); // true 判断数字是否是NaN

      Number.isInteger(100.0); // true 判断数字是否是整数

      // Number.EPSILON 极小常量,可以定义一个函数,判断两个值是否相等
      function isEqual(x, y) {
        return Math.abs(x - y) < Number.EPSILON;
      }
      console.log(isEqual(0.1 + 0.2, 0.3)); // true

      // 直接舍弃小数
      Math.trunc(1.8); // 1
      Math.trunc(-1.8); // -1

      // 判断一个数是正数、负数还是零,存在隐式转换
      Math.sign(-100); // -1
      Math.sign(+100); // 1
      Math.sign(-0); // -0
      Math.sign(+0); // 0
      Math.sign("haha"); // NaN

数组的扩展

      // 扩展运算符 ...
      let arr1 = [1, 2, 3];
      let arr2 = [1, 2, 3];
      let newArr = [...arr1, ...arr2]; // [1, 2, 3, 1, 2, 3]

      // 将类数组结构转换成数组 Array.from()
      function fn() {
        Array.from(new Set(arguments)); // [1, 2, 3, 4, 5]
      }
      fn(1, 2, 3, 4, 4, 5, 5);

      // 创建数组 Array.of()
      let arr3 = Array(3); // [空属性 × 3] 原始方法创建数组的弊端
      let arr4 = Array.of(4); // [4]

      // 从前向后查找数组元素 find findIndex()
      // 从后向前查找数组元素 findLast findLastIndex() =>Es13
      let arr = [111, 222, 333];
      let res = arr.find((item) => {
        return item > 111;
      });
      console.log(res); // 222

      // 填充元素 fill()
      let emptyArr = [1, 2, 3];
      emptyArr.fill("替换元素", 0, 1); // ['替换元素', 2, 3]

对象的扩展

      // 对象简写
      let name = "moudleA";
      let obj = {
        name,
        [name + "fn1"]: "方法1",
        [name + "fn2"]: "方法2",
      };
      // {name: 'moudleA', moudleAfn1: '方法1', moudleAfn2: '方法2'}

      let obj1 = {
        name: "haha",
      };

      let obj2 = {
        age: "lala",
      };

      // 对象的合并 es6
      Object.assign(obj1, obj2); // {name: 'haha', age: 'lala'} 第一个参数的原对象会被影响
      // 对象的合并 es9
      console.log({ ...obj1, ...obj2 }); // {name: 'haha', age: 'lala'} 原对象不会被影响

      // Object.is() 与 === 不同点

      // 1.可以判断NaN和自身的相等
      NaN === NaN; // false
      Object.is(parseInt("name"), NaN); // true

      // 2.可以判断+0和-0的不相等
      +0 === -0; // true
      Object.is(+0, -0); // false

函数的扩展

      // 参数默认值
      function name(a = 1, b) {}

      // rest参数 剩余参数
      function fn(a, ...params) {
        console.log(a); // 1
        console.log(...params); // 2,3,4,5
      }
      fn(1, 2, 3, 4, 5);

      // 箭头函数
      // 1. 只有一行代码可以简写
      let arr = ["a", "b", "c"];
      let newArr = arr.map((item) => `<li>${item}<li/>`); // ['<li>a<li/>', '<li>b<li/>',                 
      '<li>c<li/>']

      // 2.如果返回的是一个对象(大括号外面套一层小括号)
      let objFun = () => ({ name: "haha", age: 10 }); // {name: 'haha', age: 10}

      // 无法访问arguments,无法new
      // 箭头函数本身没有this,它的this指向箭头函数的外部作用域

Symbol 类型

      // 定义一个Symbol类型的变量
      let s1 = Symbol();

      // 不能进行运算
      // 有隐式转换
      if (s1) {
        console.log(111); // 111
      }

      // 定义Symbol类型的变量时,最好放在一起使用,代码简洁易懂
      let keys = {
        name: Symbol("name"),
        age: Symbol("age"),
      };
      let obj = {
        [keys.name]: "不使用钥匙是拿不到值的",
        [keys.age]: 18,
      };
      // {Symbol(name): '不使用钥匙是拿不到值的', Symbol(age): 18}

      // for in 无法遍历Symbol类型

      // Reflect.ownKeys() 可以拿到对象所有的属性(包括Symbol类型的属性)
      Reflect.ownKeys(obj).forEach((item) => {
        console.log(item, obj[item]);
      }); // Symbol(name) '不使用钥匙是拿不到值的' Symbol(age) 18

      // 作为常量
      const eat = Symbol();
      const sleep = Symbol();

      function play(type) {
        switch (type) {
          case eat:
            console.log("吃饭");
            break;
          case sleep:
            console.log("睡觉");
            break;
          default:
            break;
        }
      }
      play(sleep); //睡觉

iterator 迭代器

      // 迭代器 Iterator 一个数据结构只要具有Symbol.iterator属性,就认为是可遍历的
      let arr = [1, 2, 3];
      let iter = arr[Symbol.iterator]();

      console.log(iter.next()); // {value: 1, done: false}
      console.log(iter.next()); // {value: 2, done: false}
      console.log(iter.next()); // {value: 3, done: false}
      console.log(iter.next()); // {value: undefined, done: true}

      // 原生默认具备iterator接口的数据结构
      // Array Set Map String arguments对象 NodeList对象

      // 利用迭代器封装遍历对象中可遍历的属性
      let obj = {
        name: "遍历对象",
        age: 18,
        list: [111, 222, 333],
        // 迭代器
        [Symbol.iterator]() {
          let index = 0;
          return {
            next: () => {
              return {
                value: this.list[index++],
                done: index === this.list.length + 1 ? true : false,
              };
            },
          };
        },
      };
      for (const item of obj) {
        console.log(item); // 111 222 333
      }

      // 手写迭代器(ts)
      const fn = (args: any) => {
      let it: Iterator<any> = args[Symbol.iterator]();
      let next: any = { done: false };
        while (!next.done) {
          next = it.next();
          if (!next.done) {
          // console.log(next);
            if (next.value.length >= 2) {
              console.log(`${next.value[1]}是${next.value[0]}`);
            }
          }
        }
      };

Set数据结构

      // Set 结构类似于数组,但成员的值都是唯一的,没有重复的值
      // 利用Set结构数组去重
      let arr = [1, 2, 2, 3, 4, 5, 5, 6];
      let [...res] = new Set(arr); // [1, 2, 3, 4, 5, 6]

      // 添加
      set.add(1);

      // 长度
      console.log(set.size);

      // 删除
      set.delete(1);

      // 检查
      console.log(set.has(1)); // true

      // 封装一个可以去重复杂数组的函数
      function fn(arr) {
        let res = new Set();
        return arr.filter((item) => {
          let id = JSON.stringify(item);
          if (res.has(id)) {
            return false;
          } else {
            res.add(id);
            return true;
          }
        });
      }

Map数据结构

      // Map 用来存储键值对结构的数据(key-value)
      // Map 和 Object 主要区别:
      // 1. Object中的属性只能是字符串或符号
      // 2. Map任何类型的值都可以成为数据的key

      const obj = {
        name: "1",
        age: 18,
      };
      console.log(obj);

      // 创建map对象
      const map = new Map();
      map.set(obj, "纳西妲");
      map.set(undefined, "妮露");

      //   // 存值
      //   map.set(obj, '啦啦')
      //   console.log(map)

      //   // 取值
      //   console.log(map.get(obj))

      //   // 删除
      //   map.delete(obj)

      //   // 查找
      //   console.log(map.has(NaN)) // false

      //   // 清空
      //   console.log(map.clear())

      //   // 长度
      //   console.log(map.size)

      // 将数据类型为Map的对象转换为数组
      const [...arr] = map;
      console.log(arr);

      // 遍历Map
      for (const [key, value] of map) {
        console.log(key, value);
      }

      // 获取所有的key
      for (const key of map.keys()) {
        console.log(key);
      }

      // 获取所有的value
      for (const value of map.values()) {
        console.log(value);
      }

      map.forEach((item, index) => {
        console.log(item, index);
      });

Proxy代理

      // 在Proxy代理出现之前是用 Object.defineProperty 来拦截更改/获取dom行为
      // 缺点 每次只能拦截一个属性,只能拦截对象
      // let obj = {};
      // Object.defineProperty(obj, "data", {
      //   get() {
      //     console.log("get");
      //   },
      //   set(value) {
      //     console.log("set", value);
      //   },
      // });

      // Proxy 可以拦截所有数据类型
      let obj = {};
      let proxy = new Proxy(obj, {
        get(target, key) {
          // 对于Set或Map这样的数据结构,需要判断如果是方法就修改this指向
          let value = target[key];
          if (value instanceof Function) {
            return value.bind(target);
          }
          return value;
        },
        set(target, key, value) {
          if (key === "data") {
            box.innerHTML = value;
          }
          // 将值赋值给目标
          // target[key] = value;
        },
      });

Reflect反射

      // 代替Object 某些方法
      let obj = {};
      Reflect.defineProperty(obj, "name", {
        value: "haha",
        writable: false,
        enumerable: false,
      });
      // 修改某些Object 方法返回结果
      if (Reflect.defineProperty(target, property, attributes)) {
        // success
      } else {
        // fail
      }

      // 命令式变为函数行为
      Reflect.has(obj, "name"); //true
      Reflect.deleteProperty(obj, "name");

      // 设置和获取
      Reflect.set(obj, "age", 10);
      Reflect.get(obj, "age");

      // 最重要的作用是配合Proxy设置/获取属性或方法
      let proxy = new Proxy(obj, {
        get(target, key) {
          // 获取相应的方法
          let value = Reflect.get(target, key);
          // 如果是函数,修改this指向
          if (value instanceof Function) {
            return value.bind(target);
          }
          return value;
        },
        set(target, key, value) {
          // 执行默认行为
          Reflect.set([...arguments]);
        },
      });

Promise对象

      // 基础写法
      let promise = new Promise((res, rej) => {
        setTimeout(() => {
          res(1000);
        }, 200);
      });
      promise
        .then((res) => {
          console.log("success", res);
        })
        .catch((err) => {
          console.log("fail", err);
        });

      // 有三种状态,pendding状态 fulfilled状态 rejected状态
      // 从pendding状态只能转换为fulfilled状态和rejected状态之间的一种状态,且改变后会凝固,不会再进行改变。

      // 解决回调地狱的问题 => 利用链式调用
      promise
        .then((res) => {
          console.log("success", res); // success 1000
          // 如果return 非Promise类型,直接变为 fulfilled状态
          // 如果return Promise类型,则根据这个Promise的状态去返回。
          return res;
        })
        .then((res) => {
          console.log("success", res); // success 1000
        })
        .catch((err) => {
          console.log("fail", err);
        });

      // Promise.all([]) 等全部promise执行完了之后再执行

      Promise.all([promise1, promise2])
        .then((result) => {
          console.log(result);
        })
        .catch((err) => {
          console.log(err);
        });

      // Promise.race() 等最快的promise执行完了就执行

      Promise.race([promise1, promise2])
        .then((result) => {
          console.log(result);
        })
        .catch((err) => {
          console.log(err);
        });

Generator生成器函数

      // 基础使用
      function* gen() {
        console.log(1);
        yield; // 产出
        console.log(2);
        yield;
        console.log(3);
      }

      let g = gen();
      g.next(); // 1
      g.next(); // 2
      g.next(); // 3

class语法

      // 类是对象模板
      class Person {
        // 属性
        name = "我是实例属性"; // 大部分情况下用实例属性
        static props = "我是静态属性";

        // 方法
        sayHello() {
          console.log("我是实例方法", this.name); // this指向当前实例
        }

        static sayHi() {
          console.log("我是类方法", this); // this指向类
        }
      }

      class Dog {}

      // 调用构造函数创建对象(实例)
      //     实例           类
      const person1 = new Person();
      const dog1 = new Dog();

      // 利用 instanceof 可以判断一个对象是否由某个类创建
      console.log(dog1 instanceof Person); // false
      console.log(dog1 instanceof Dog); // true

      console.log(person1.name); // 实例属性只能通过实例访问
      console.log(Person.props); // 静态属性(类属性)只能通过类访问

      // 调用实例方法
      person1.sayHello();

      // 调用类方法
      Person.sayHi();

class继承

      // 可以通过extends关键字来完成继承,最大的作用就是,在不修改类的情况下,对其进行扩展
      // OCP 开闭原则,对修改关闭,对扩展开放
      class Animal {
        constructor(name) {
          this.name = name;
        }
        sayHello() {
          console.log(`动物在叫!`);
        }
      }

      class Snake extends Animal {
        // 重写构造函数
        constructor(name, age) {
          // 重写构造函数时,第一行代码必须是super()
          super(name); // 调用父类的构造函数
          this.age = age;
        }
        // 重写父类的方法
        sayHello() {
          // 在方法中可以使用super来调用父类的方法
          super.sayHello();
          console.log(`嘶嘶嘶!`);
        }
      }
      const snake1 = new Snake("蛇", 10);
      snake1.sayHello();
      console.log(snake1); // Snake {name: '蛇', age: 10}

 EMS规范和CJS规范

ES7

求幂运算符

Math.pow(3,2)===3**2 // 9

 数组的includes方法

[1,2,NaN].includes(NaN) // true

[1,2,NaN].indexOf(NaN) // -1 数组的indexOf方法判断不出数组中是否有NaN

ES8

async和await

      // 解决回调地狱的最优方案
      function ajax1() {
        return new Promise((res, rej) => {
          setTimeout(() => {
            res("第一个请求返回的值");
            // rej("第一个请求失败");
          }, 1000);
        });
      }

      function ajax2() {
        return new Promise((res, rej) => {
          setTimeout(() => {
            res("成功接收第一个请求的返回值");
            // rej("第二个请求失败");
          }, 2000);
        });
      }

      // 第一种写法
      async function test1() {
        let res1 = await ajax1();
        let res2 = await ajax2(res1);
        return res2;
      }
      test1()
        .then((result) => {
          // 渲染页面
          console.log(result);
        })
        .catch((err) => {
          // 处理错误
          console.log(err);
        });

      // 第二种写法
      async function test2() {
        try {
          let res1 = await ajax1();
          console.log(res1);
          let res2 = await ajax2(res1);
          console.log(res2);
          console.log("渲染页面");

          // 如何使用Promise.all方法
          // let res = await Promise.all([ajax1(), ajax2(res1)]);
          // console.log(res); // ['第一个请求返回的值', '成功接收第一个请求的返回值']
        } catch (error) {
          console.log(error, "处理错误");
        }
      }
      test2();

对象方法扩展

      // 对象的获取操作
      let obj = {
        name: "八重神子",
        age: 500,
        get changeName() {
          return 666;
        },
        set changeName(value) {
          this.name = value;
        },
      };
      console.log(Object.keys(obj)); // es6 只取key ['name', 'age']
      console.log(Object.values(obj)); // 只取值 ['八重神子', 500]
      console.log(Object.entries(obj)); // key和值都获取 0: (2) ['name', '八重神子'] 1: (2) ['age', 500]

      // 对象的复制操作,可以把对象里的方法一起复制
      let obj1 = {};
      Object.defineProperties(obj1, Object.getOwnPropertyDescriptors(obj));

字符串填充

      // 字符串填充到指定长度
      let str = "天道酬勤";
      str.padEnd(10, "1"); // 天道酬勤111111
      str.padStart(5, "6"); // 6天道酬勤

ES9

rest与扩展运算符

      // 剩余参数
      function name(a, ...b) {}

      //扩展运算符
      let obj = { a: 1, b: 2 };
      // 这种方法复制只能深复制一层
      // 如果对象属性有复杂数据类型则无法实现深复制
      let obj1 = { ...obj };

正则命名捕获分组

      let str = "今天是2022-10-10";
      let reg = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/;
      let res = reg.exec(str);
      let { year, month, day } = res.groups; // 2022 10 10

Promise.finally

      // Promise.finally 最后执行,不管promise状态是成功还是失败
      function ajax() {
        return new Promise((res, rej) => {
          rej("失败");
        });
      }

      ajax()
        .then((result) => {})
        .catch((err) => {})
        .finally(() => {
          // 不管成功还是失败都隐藏loading
        });

异步迭代

      // 有一个任务数组,执行任务按顺序执行,任务1,任务2,任务3,以此类推(前提在for循环中执行)

      // 1. 写一个ajax请求
      function timer(t) {
        return new Promise((res, rej) => {
          setTimeout(() => {
            res("data-" + t);
          }, t);
        });
      }

      // 写一个异步生成器生成异步任务
      async function* gen() {
        yield timer(1000);
        yield timer(2000);
        yield timer(3000);
      }

      // 利用 for await 遍历异步任务
      async function test() {
        let g = gen();
        let arr = [g.next(), g.next(), g.next()];
        for await (const item of arr) {
          console.log(item);
        }
      }
      test();

ES10

Object.fromEntries

      // 用法1 将Map结构转化成对象
      let arr = new Map();
      arr.set("name", "haha");
      arr.set("age", 18);
      Object.fromEntries(arr); // {name: 'haha', age: 18}

      // 用法2 将url参数转化成对象
      let url = "name=lala&age=20";
      let searchParams = new URLSearchParams(url);
      Object.fromEntries(searchParams); // {name: 'lala', age: '20'}

      // 用法三 转换对象形式
      let obj = {
        A: ["A1", "A2", "A3"],
        B: ["B1", "B2"],
        C: ["c1"],
      };
      let newArr = [];
      for (const key in obj) {
        newArr.push([key, obj[key].length]);
      }
      Object.fromEntries(newArr) // {A: 3, B: 2, C: 1}

 trimStart和trimEnd

删除字符串前面的空格 str.trimStart() 
删除字符串后面的空格 str.trimEnd()

flat()和flatMap() 

      // 扁平化 flat() flatMap()
      [1, 2, 3, [4, 5, 6]].flat(); // [1, 2, 3, 4, 5, 6]
      let addr = [
        {
          name: "A",
          location: [1, 2, 3, 4],
        },
        {
          name: "B",
          location: [5, 6, 7, 8],
        },
      ];

      let resArr = addr.flatMap((item) => {
        return item.location;
      });
      console.log(resArr); // [1, 2, 3, 4, 5, 6, 7, 8]

 symbol.description 

      // 根据描述符查找Symbol属性
      let s = Symbol("name");
      s.description // name

ES11

Promise.allSettled

      function ajax(flag, t) {
        return new Promise((res, rej) => {
          setTimeout(() => {
            if (flag) {
              res("成功");
            } else {
              rej("失败");
            }
          }, t);
        });
      }
      // 把全部成功的请求返回,不用捕获失败的请求
      Promise.allSettled([
        ajax(true, 1000),
        ajax(true, 2000),
        ajax(false, 3000),
      ]).then((result) => {
        let res = result.filter((item) => item.status === "fulfilled");
        let newRes = res.flatMap((item) => item.value); // ['成功', '成功']
      });

Module新增

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>es11</title>
  </head>
  <button id="login">登录</button>
  <body>
    <script>
      function fn() {
        return "管理员";
      }

      let login = document.querySelector("#login");
      login.onclick = function () {
        let role = fn();
        render(role);
      };
      // 动态导入
      async function render(role) {
        if (role === "管理员") {
          let res1 = await import("./1.js"); // 返回promise对象
          console.log(res1);
        } else {
          let res2 = await import("./2.js");
          console.log(res2);
        }
      }
    </script>
  </body>
</html>
// 1.js文件

console.log("管理员js加载了", import.meta); 
// 管理员js加载了 {url: 'http://127.0.0.1:5500/Es6-Es13/1.js', resolve: ƒ}

export default {
  name: "管理员",
};

// 无侵入式从别的模块继承过来然后导出
export * as js_2 from "./2.js";

字符串的matchAll方法

      let str = `<ul>
        <li>111</li>
        <li>222</li>
        <li>333</li>
      </ul>`;

      let reg = /<li>(.*)<\/li/g;
      let obj = str.matchAll(reg);
      for (const item of obj) {
        console.log(item[1]); // 111 222 333
      }

bigint (大整数)类型

// BigInt数据类型支持范围更大的整数值,可以用任意精度表示整数

BigInt(10); // 10n 

BigInt(10) == 10; // true

BigInt(10) === 10; // false

// 如果后端给你返回的数据太大,他又不给你转换成字符串,就使用json-bigint插件进行转换
import JsonBigint from "json-bigint";

// 转换成字符串类型
// let JsonBigintStr = JsonBigint({ storeAsString: true });

// 转换成bigInt类型
let JsonBigintNative = JsonBigint({ useNativeBigInt: true });

let jsonStr = `{
        "id":9007199254740993,
        "list":[]
      }`;

// JsonBigintStr.parse(jsonStr); // { id: '9007199254740993', list: [] }
JsonBigintNative.parse(jsonStr); // { id: 9007199254740993n, list: [] }

globalThis 顶层对象

// 在不同平台,都可以拿到当前环境的顶层对象,在跨平台开发时就无须再配置。

// 在浏览器环境 globalThis === window 

空值合并运算符 ??

      // 只要  ?? 前面不是null或undefined 就返回前面的值
      // let str = null ?? "签名"; // 签名
      // let str = undefined ?? "签名"; // 签名
      // let str = 0 ?? "签名"; // 0

可选链操作符 ?.

      // 当问号前面的值没有或为undefined时,直接返回undefined,不至于使代码报错
      let obj = {
        name: "张三",
        // location: {
        //   now: "beijing",
        // },
      };
      console.log(obj?.location?.now); // undefined

ES12

新增逻辑操作符

      let a = true;
      let b = false;
      a &&= b; // false
      a ||= b; // false
      let obj = {
        // name: 1,
      };
      obj.name ??= "默认名字"; // 默认名字

字符串的replaceAll 方法

      // 可以全部替换
      let str = `1,1,1,1`;
      str.replaceAll("1", "*"); // *,*,*,*

Promise.any

      let ajax1 = function () {
        return new Promise((res, rej) => {
          rej("纳西妲");
        });
      };
      let ajax2 = function () {
        return new Promise((res, rej) => {
          res("八重神子");
        });
      };
      let ajax3 = function () {
        return new Promise((res, rej) => {
          res("神里绫华");
        });
      };
      // 只要任意请求成功,就直接返回该成功结果,全部失败才到catch
      Promise.any([ajax1(), ajax2(), ajax3()])
        .then((result) => {
          console.log(result);
        })
        .catch((err) => {
          console.log("err", err);
        });

WeakRef

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>es12</title>
  </head>
  <div id="div">1111</div>
  <body>
    <script>
      // 强引用
      let obj = {
        name: "大理石",
      };

      // Map(Set)结构存在的问题
      // let m1 = new Map();
      // m1.set(obj, "哈哈");

      // obj = null;
      // 因为引用计数机制,obj依然存在在m1里,没有被垃圾回收(内存泄漏)

      // 弱引用 WeakMap WeakSet 只能存储复杂数据类型,size,for不能用
      let m2 = new WeakMap();
      m2.set(obj, "啦啦");
      obj = null;
      // 因为是弱引用,不存在引用计数机制,所以m2中的obj被回收了

      let dom = new WeakRef(document.querySelector("#div"));
      dom.deref(); // <div id="div">1111</div>
    </script>
  </body>
</html>

ES13

类新增特性

      class Person {
        // 初始值可以直接定义
        state = {
          name: "haha",
          age: 18,
        };
        sex = "男";

        // 实例私有属性
        #play = "打游戏";
        playGame() {
          return this.#play;
        }

        // 静态私有属性配合静态公开方法
        static #watch = "看电视";
        static watchTv() {
          return this.#watch;
        }

        // 静态代码块(可以写多个)
        static obj = new Map();
        static {
          this.obj.set("name", "无量天尊");
          this.obj.set("age", 8000);
        }
        static {
          console.log(this.obj); // Map(2) {'name' => '无量天尊', 'age' => 8000}
        }

        // 判断某个属性是不是该类的私有属性
        hasObj() {
          return #play in this;
        }
      }
      let person = new Person();
      person.playGame(); // 打游戏
      Person.watchTv(); // 看电视
      person.hasObj(); // true

顶层 await 

// js文件

function ajax() {
  return new Promise((res, rej) => {
    setTimeout(() => {
      res("成功");
    }, 2000);
  });
}

// 当有数据是异步导出时,可以使用顶层 await 接收数据
let data = await ajax();

export default {
  name: "haha",
  data,
};


// html文件

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>es13</title>
  </head>
  <body>
    <script type="module">
      // 异步导出配合动态导入使用最佳
      console.log("不能被阻塞的初始化数据"); // 不能被阻塞的初始化数据
      let moduleA = await import("./ajax.js");
      console.log(moduleA); // Module {Symbol(Symbol.toStringTag): 'Module'}
    </script>
  </body>
</html>

at函数

let arr = [1,2,3,4]
arr.at(0) // 第一个元素
arr.at(-1) // 倒数第一个元素

// 字符串也适用

findLast 和 findLastIndex

      let arr = [10, 20, 30, 40];
      let res = arr.findLast((value) => value < 40);
      let resIndex = arr.findLastIndex((value) => value < 40);
      console.log(res); // 30 从后面查找并返回第一个符合条件的元素
      console.log(resIndex); // 2 从后面查找并返回第一个符合条件的元素的索引

catch捕获错误添加原因

      function getData() {
        try {
          console.log(aaa);
        } catch {
          throw new Error("不符合规则", {
            cause: {
              a: "十连双黄",
              b: "单抽出金",
            },
          });
        }
      }
      try {
        getData();
      } catch (error) {
        console.log(error, error.cause);
        /* Error: 不符合规则
           at getData (es13.html:27:17)
           at es13.html:36:9 {a: '十连双黄', b: '单抽出金'}*/
      }

  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
ES6-ES12是JavaScript的不同版本,每个版本都引入了新的特性和改进。以下是一些ES6到ES12的新特性的示例: ES6(2015年): 1. 箭头函数:简化了函数的语法。 2. 模板字面量:使用反引号(`)来创建多行字符串和插入变量。 3. 解构赋值:从对象或数组中提取值并赋给变量。 4. let和const:引入块级作用域的变量声明方式。 5. Promise:处理异步操作的更强大的方式。 ES7(2016年): 1. Array.prototype.includes():判断数组是否包含某个元素。 2. 指数操作符:使用双星号(**)进行指数运算。 ES8(2017年): 1. async/await:更简洁地处理异步操作。 2. Object.values()和Object.entries():从对象中提取值或键值对。 ES9(2018年): 1. Rest/Spread属性:通过...语法来处理函数参数和对象字面量。 2. Promise.prototype.finally():在Promise结束时执行操作。 ES10(2019年): 1. Array.prototype.flat()和Array.prototype.flatMap():用于处理嵌套数组的方法。 2. Object.fromEntries():将键值对列表转换为对象。 ES11(2020年): 1. 可选链操作符(Optional chaining):简化了访问深层嵌套属性的方式。 2. Nullish coalescing操作符:提供了一种默认值的设定方式。 ES12(2021年): 1. Promise.any():在多个Promise中返回最快解决的结果。 2. Logical Assignment Operators:提供了逻辑运算符与赋值的结合方式。 当然,以上仅是一些主要的新特性ES6-ES12还有其他许多有用的功能和语法改进。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微光无限

破晓的日子还有很多!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值