本文中将介绍并解释在规范的最新草案中已被接受的提案的特性。

每个特性提案都遵循一个过程,在这个过程中,它经历了不同的阶段,直到stage 4,这表明新增功能已准备好包含在正式的ECMAScript标准中,并将包含在最快的实用标准修订版中。以下功能已经完成,处于stage 4并已添加到ECMAScript最新草案中。

1、声明类的字段

到目前为止,在ES规范中,类的字段定义和初始化是在类的构造函数中完成的。但是在新的提案中,类字段可以在类的顶层被定义和初始化.

class Point {
   name;
   title;
   size = 1;
}

2、私有方法&字段

#前缀来定义类的私有方法和字段。

class Person {
   name;
   #age;
   get #age(){
       return #age;
   }
  $initValue(){
      this.name = '';
      this.#age = 12;
  }
 }

3、类的静态公共方法和字段

在之前的类的字段私有方法提案的基础上,为JavaScript类增加了静态公共字段静态私有方法静态私有字段的特性。

class Enum {
  static collectStaticFields() {
    // Static methods are not enumerable and thus ignored
    this.enumKeys = Object.keys(this);
  }
}
class ColorEnum extends Enum {
  static red = Symbol('red');
  static green = Symbol('green');
  static blue = Symbol('blue');
  static _ = this.collectStaticFields(); // (A)

  static logColors() {
    for (const enumKey of this.enumKeys) { // (B)
      console.log(enumKey);
    }
  }
}
ColorEnum.logColors();
// Output:
// 'red'
// 'green'
// 'blue'

4、ECMScript 类静态初始化块

类静态块提议提供了一种优雅的方式,在类声明/定义期间评估静态初始化代码块,可以访问类的私有字段

class Person {
   static name;
   age;
}
try {
   Person.name = getNameA();
} catch {
   Person.name = getNameB();
}

5、检测私有字段

当我们试图访问一个没有被声明的公共字段时,会得到未定义的结果,同时访问私有字段会抛出一个异常。我们根据这两个行为来判断是否含有公共字段和私有字段。但是这个建议引入了一个更有趣的解决方案,它包括使用in操作符,如果指定的属性/字段在指定的对象/类中,则返回真,并且也能判断私有字段.

class Person {
   name;
   #age;
   get #age(){
       return #age;
    }
    $initValue(){
       this.name = '';
       this.#age = 12;
    }
    static hasAge(person){
      return #gae in person;
    }
 }

6、正则匹配索引

该提案提供了一个新的 /dflag,以获得关于输入字符串中每个匹配的开始和索引位置结束的额外信息。

const reg = /test(\d)/g;
const reg2022 = /test(\d)/dg;
const srt = 'test1test2';
const arr = [...str.matchAll(reg)];
const arr2022 = [...str.matchAll(reg2022)];
arr[0] //
arr2022[0] //


7、在所有内置的可索引数据上新增.at()方法

新增一个新的数组方法,通过给定的索引来获取一个元素。当给定的索引为正数时,这个新方法的行为与使用括号符号的访问相同,但是当我们给定一个负整数的索引时,它就像python的 "负数索引 "一样工作,这意味着at()方法以负整数为索引,从数组的最后一项往后数。所以该方法可以被执行为array.at(-1),它的行为与array[array.length-1]相同,在下面的例子中可以看到。

const list = [1,2,3,4,5,6];
console.log(list.at(-1)); // 6
console.log(list.at(-2)); // 5

8、Object.hasOwn(object, property)

简单讲就是使用Object.hasOwn替代Object.prototype.hasOwnProperty.call

const person = {name: 'lxm'}
console.log(Object.prototype.hasOwnProperty.call(person, 'name')) // true

console.log(Object.hasOwn(person, 'name')) // true

9、Error Cause

proposal-error-cause这一提案,目的主要是为了便捷的传递导致错误的原因,如果不使用这个模块,想要清晰的跨越多个调用栈传递错误上下文信息,通常要这么做:

async function doJob() {
  const rawResource = await fetch('//domain/resource-a')
    .catch(err => {
      // How to wrap the error properly?
      // 1. throw new Error('Download raw resource failed: ' + err.message);
      // 2. const wrapErr = new Error('Download raw resource failed');
      //    wrapErr.cause = err;
      //    throw wrapErr;
      // 3. class CustomError extends Error {
      //      constructor(msg, cause) {
      //        super(msg);
      //        this.cause = cause;
      //      }
      //    }
      //    throw new CustomError('Download raw resource failed', err);
    })
  const jobResult = doComputationalHeavyJob(rawResource);
  await fetch('//domain/upload', { method: 'POST', body: jobResult });
}

await doJob(); // => TypeError: Failed to fetch

而按照这一提案的语法:

sync function doJob() {
  const rawResource = await fetch('/domain/resource-a').catch(err => {
    throw new Error(‘Download raw resource failed’, { cause: err });
  });

  const jobResult = doComputationalHeavyJob(rawResource);
  await fetch('/domain/upload', { method:POST, body: jobResult }).catch(err => {
    throw new Error(‘Upload job result failed’, { cause: err });
  });
}

try {
  await doJob();
} catch (e) {
  console.log(e);
  console.log(‘Caused by’, e.cause);
}
// Error: Upload job result failed
// Caused by TypeError: Failed to fetch

results matching ""

    No results matching ""