ES7 - Array Includes

在ES7之前,如果我们想判断一个数组中是否包含某个元素,需要通过 indexOf 获取结果,并且判断是否为 -1。

在ES7中,我们可以通过includes来判断一个数组中是否包含一个指定的元素,根据情况,如果包含则返回 true,否则返回false。

ES7 –指数exponentiation运算符

在ES7之前,计算数字的乘方需要通过 Math.pow 方法来完成。

在ES7中,增加了 ** 运算符,可以对数字来计算乘方

ES8 Object values

之前我们可以通过 Object.keys 获取一个对象所有的key

在ES8中提供了 Object.values 来获取所有的value值:

ES8 Object entries

通过 Object.entries 可以获取到一个数组,数组中会存放可枚举属性的键值对数组。

  • 可以针对对象、数组、字符串进行操作;

ES8 - String Padding

某些字符串我们需要对其进行前后的填充,来实现某种格式化效果,ES8中增加了 padStart 和 padEnd 方法,分别是对字符串的首尾进行填充的。

我们简单具一个应用场景:比如需要对身份证、银行卡的前面位数进行隐藏:

ES8 - Trailing Commas

在ES8中,我们允许在函数定义和调用时多加一个逗号:

ES8 - Object Descriptors

Object.getOwnPropertyDescriptors :

Async Function:async、await

ES9新增知识点

Async iterators

Object spread operators

Promise finally

ES10 - flat flatMap

flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。

flatMap() 方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。

  • 注意一:flatMap是先进行map操作,再做flat的操作;
  • 注意二:flatMap中的flat相当于深度为1;

      // 1.flat的使用
      // 将一个数组,按照指定的深度遍历,将遍历到的元素和子数组组成一个新的数组,进行返回
      const nums = [
        12,
        22,
        [111, 222],
        [333, 444],
        [
          [123, 321],
          [231, 321],
        ],
      ];

      const newNul1 = nums.flat(1);
      console.log(newNul1);
      const newNul2 = nums.flat(2);
      console.log(newNul2);
      
      // 2.flatMap的使用
      // 1.对数组中每一个元素应用一次传入的map对应的函数
      const message = ["hello world", "Hello What", "你好 世界"];
      
      // 自己的方式: for循环
      /* const newInfos = [];
      for (const item of message) {
        const infos = item.split(" ");
        console.log(infos);
        for (const info of infos) {
          newInfos.push(info);
        }
      }
      console.log(newInfos); */

      // 先进行map,在进行flat操作
      /*  const newMessages = message.map((item) => item.split(" "));
      const finalMessages = newMessages.flat(1);
      console.log(finalMessages); */

      // 3.flatMap
      const finalMessages = message.flatMap((item) => item.split(" "));
      console.log(finalMessages);

ES10 - Object fromEntries

在之前,我们可以通过 Object.entries 将一个对象转换成 entries

那么如果我们有一个entries了,如何将其转换成对象呢?

  • ES10提供了 Object.formEntries来完成转换:

那么这个方法有什么应用场景呢?

      // 1.对象
      const obj = {
        name: "why",
        age: 18,
        height: 1.77,
      };

      const entries = Object.entries(obj);
      const info = Object.fromEntries(entries);
      console.log(info);

      // 2.应用
      const searchString = "?name=why&age=14&height=1.66";
      const params = new URLSearchParams(searchString);
      console.log(params.get("name"));
      console.log(params.get("age"));
      console.log(params.entries());

      /* for (const item of params.entries()) {
        console.log(item);
      } */

      const paramsObj = Object.fromEntries(params);
      console.log(paramsObj);

ES10 - trimStart trimEnd

去除一个字符串首尾的空格,我们可以通过trim方法,如果单独去除前面或者后面呢?

  • ES10中给我们提供了trimStart和trimEnd

ES10 其他知识点

Symbol description

Optional catch binding

ES11 - BigInt

在早期的JavaScript中,我们不能正确的表示过大的数字:

  • 大于MAX_SAFE_INTEGER的数值,表示的可能是不正确的。

那么ES11中,引入了新的数据类型BigInt,用于表示大的整数:

  • BigInt的表示方法是在数值的后面加上n

ES11 - Nullish Coalescing Operator

ES11,Nullish Coalescing Operator增加了空值合并操作符:

	  let info = 0;
      /*  info = info || "默认值";
      console.log(info); */

      info = info ?? "默认值";
      console.log(info);

ES11 - Optional Chaining

可选链也是ES11中新增一个特性,主要作用是让我们的代码在进行null和undefined判断时更加清晰和简洁:

      const obj = {
        name: "what",
        friend: {
          name: "rick",
          running: function () {
            console.log(this.name);
          },
        },
      };

      // obj.friend.running(); 直接调用
      /*
      if判断
      if(obj.friend&&obj.friend.running){
        obj.friend.running();
      } */
      
      // 可选链
      obj?.friend?.running?.();

ES11 - Global This

在之前我们希望获取JavaScript环境的全局对象,不同的环境获取的方式是不一样的

  • 比如在浏览器中可以通过this、window来获取;
  • 比如在Node中我们需要通过global来获取;

在ES11中对获取全局对象进行了统一的规范:globalThis

ES11 - for…in标准化

在ES11之前,虽然很多浏览器支持for…in来遍历对象类型,但是并没有被ECMA标准化。

在ES11中,对其进行了标准化,for…in是用于遍历对象的key的:

ES11 其他知识点

Dynamic Impor

Promise.allSettled

import meta

ES12 - FinalizationRegistry

FinalizationRegistry 对象可以让你在对象被垃圾回收时请求一个回调。

  • FinalizationRegistry 提供了这样的一种方法:当一个在注册表中注册的对象被回收时,请求在某个时间点上调用一个清理回调。(清理回调有时被称为 finalizer );

你可以通过调用register方法,注册任何你想要清理回调的对象,传入该对象和所含的值;

      let obj = { name: "why", age: 18 };
      let info = { name: "what", age: 17 };

      const finalRegistry = new FinalizationRegistry((value) => {
        console.log("对象被回收了", value);
      });

      finalRegistry.register(obj, "why");
      finalRegistry.register(info, "what");

      // obj = null;
      info = null;

ES12 - WeakRefs

如果我们默认将一个对象赋值给另外一个引用,那么这个引用是一个强引用:

  • 如果我们希望是一个弱引用的话,可以使用WeakRef;
      let info = { name: "why", age: 18 };
      let obj = new WeakRef(info);
      let obj2 = new WeakRef(info);

      const finalRegistry = new FinalizationRegistry((value) => {
        console.log("对象被回收了", value);
      });
      
      finalRegistry.register(info, "info");
      
      /*
      不要这样写,这样拿到之后又赋值会产生强引用  
      const infoRef = obj.deref();
      console.log(infoRef);
      console.log(infoRef.name, infoRef.age); */

      setTimeout(() => {
        info = null;
      }, 2000);

      setTimeout(() => {
        console.log(obj.deref().name, obj.deref().age);
      }, 8000);

ES12 - logical assignment operators

	 // 赋值运算符
      const foo = "foo";
      let counter = 100;
      counter += 50;

      // 逻辑赋值运算符
      function foo2(message) {
        // message = message || "默认值";
        // message ||= "默认值";
        // message = message ?? "默认值";
        message ??= "默认值";
        console.log(message);
      }

      foo2("abc");
      foo2(0);

      // && 逻辑赋值运算符
      let obj = {
        name: "what",
        running: function () {
          console.log("running~");
        },
      };

      // 一般应用场景
      // obj && obj.running && obj.running();
      obj = obj && obj.name;
      obj &&= obj.name;
      console.log(obj);

ES12其他知识点

Numeric Separator

String.replaceAll

	  const message = "my name is what, what age is 19";
      // const newMessage = message.replace('what','why')
      const newMessage = message.replaceAll("what", "why");
      console.log(newMessage);

ES13 - method .at()

字符串、数组的at方法,它们是作为ES13中的新特性加入的:

ES13 - Object.hasOwn(obj, propKey)

Object中新增了一个静态方法(类方法): hasOwn(obj, propKey)

  • 该方法用于判断一个对象中是否有某个自己的属性;

那么和之前学习的Object.prototype.hasOwnProperty有什么区别呢?

  • 区别一:防止对象内部有重写hasOwnProperty
  • 区别二:对于隐式原型指向null的对象, hasOwnProperty无法进行判断

      const obj = {
        name: "why",
        age: 18,
        __proto__: {
          address: "广州市",
        },
      };

      console.log(obj.name, obj.age);
      console.log(obj.address);

      // console.log(obj.hasOwnProperty("name"));
      // console.log(obj.hasOwnProperty("address"));

      console.log(Object.hasOwn(obj, "name"));
      console.log(Object.hasOwn(obj, "address"));

      // 和 hasOwnProperty的区别
      const info = Object.create(null);
      info.name = "what";
      // console.log(info.hasOwnProperty("name"));
      console.log(Object.hasOwn(info,"name"));

ES13 - New members of classes

在ES13中,新增了定义class类中成员字段(field)的其他方式:

  • Instance public fields
  • Static public fields
  • Instance private fields
  • static private fields
  • static block

      class Person {
        // 对象属性: public 公共 => public instance fields
        height = 1.77;

        // 对象属性: private 私有:程序员之间约定的
        // _intro = "name is what";
        // 真正的私有属性
        #intro = "name is what";
        
        // 类属性 public
        static totalCount = "80亿";

        // 类属性: private
        static #maleTotalCount = "20亿";

        constructor(name, age) {
          // 对象中的属性: 在 constructor 中通过this设置
          this.name = name;
          this.age = age;
          this.address = "广州市";
        }

        // 静态代码块
        static {
          console.log("hello world");
          console.log("Hello Person");
        }
      }

      const p = new Person("what", 17);
      console.log(p);
      console.log(p.name, p.age, p.height, p.address /* p.#intro */);

Q.E.D.