让我们来看一看ECMAScript2022(ES13)中的新特性

news/2024/7/10 22:59:42 标签: javascript, es, ecmascript, ecmascript6, es6

ES13

  • 前言
  • 类的字段
    • 类的共有属性和类的私有属性
  • 类的私有的方法和getter/setters
  • 静态属性和方法
  • 科学检查私有变量的方式
  • 类静态代码块
  • 正则匹配返回下标
  • 在async外部使用await
  • 在所有内置的可索引数据上新增.at()方法
  • Object.hasOwn(object, property)

📒博客首页:酸狗的博客🍋
🎉欢迎关注🔎点赞👍收藏⭐️留言📝
💖热爱前端学习,期待一起交流!✨
🙏作者水平很有限,如果发现错误,求告知,多谢!🌈
😎有问题可私信我交流🙄

前言

ess=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p-g5qqs5qCR5LiK5p-g5qqs5p6c5p-g5qqs5qCR5LiL5L2g5ZKM5oiR,size_14,color_FFFFFF,t_70,g_se,x_16#pic_center" alt="在这里插入图片描述" />

从2015年起,Javascript每年都会在标准中加入一些新的特性。本篇文章将介绍几个已经到stage 4阶段的标准。一般来说,标准的提案需要经过4个阶段,第4个阶段是最后一个阶段。到达第4阶段的标准也意味着标准制定的工作已经基本结束。

现在我们来一起看一看ES2022(ES13)中的新特性:

类的字段

类的共有属性和类的私有属性

在这个标准出来之前,我们在class中是这么定义一个属性的:

javascript">class ButtonToggle extends HTMLElement {
    constructor(){
        super();
        // public field
        this.color = 'green'
        // private field
        this._value = true;
    }

    toggle(){
        this.value = !this.value
    }
}

const button = new ButtonToggle();
console.log(button.color);
// green - public fields are accessible from outside classes

button._value = false;
console.log(button._value);
// false - no error thrown, we can access it from outside the class

在构造函数中,我们定义了2个属性color_value。其中一个属性名以_开头,在现有的规范中我们一般这么命名来约定它是一个私有的变量,只能在类的内部对它进行赋值和读值。当然,目前这也仅仅只停留在约定层面,实际上我们在类的外面还是可以正常的操作这个属性的,程序并不会抛出异常。

在ES2022中,我们有一个更容易的方法来强制定义一个属性是共有的还是私有的。下面我们来看一个例子:

javascript">class ButtonToggle extends HTMLElement {

    color = 'green';
    #value = true;

    toggle(){
        this.#value = !this.#value;
    }
}
const button = new ButtonToggle();
console.log(button.color);
// green - public fields are accessible from outside classes

// SyntaxError - cannot be accessed or modified from outside the class
console.log(button.#value); 
button.#value = false;

首先,我们不再需要在构造函数中定义和初始化类的属性。其次,我们可以通过#符号来定义一个私有属性。与前面的例子不同的是,当我们在类的外部调用该私有属性时,程序会抛出异常。

类的私有的方法和getter/setters

与上面的例子类似,我们现在可以定义一个私有的方法和getter/setters方法,如下代码所示:

javascript">class ButtonToggle extends HTMLElement {

    color = 'green'
    #value = true;

    #toggle(){
        this.#value = !this.#value
    }

    set #setFalseValue(){
        this.#value = false;
    }
}
const button = new ButtonToggle();
// SyntaxError - cannot be accessed or modified from outside the class
button.#toggle();
// SyntaxError - cannot be accessed or modified from outside the class
button.#setFalseValue;

在代码中,我们将toggle方法用#标记变为私有的。这样一来,#toggle方法只能类的内部进行调用,否则也将抛出异常。

静态属性和方法

静态属性和方法这个概念在其它的编程语言中早就已经有了,Javascript也会在2022的标准中加入它。(早就该加了😅)

在过往,静态属性或方法只能通过原型链来调用。如果我们想给类定义一个静态的方法,我们需要在类的外部进行声明,如下代码所示:

javascript">class ButtonToggle extends HTMLElement {
    // ... class body
}
ButtonToggle.toggle(){
    // static method define outside of the class body
}

在ES2022中提供了static关键字来允许开发人员在类中声明一个静态属性或方法,可以直接通过类来调用,如下代码所示:

javascript">class ButtonToggle extends HTMLElement {

    #value = true;

    static toggle(){
        this.#value = !this.#value
    }
}
// this will work
ButtonToggle.toggle();

// SyntaxError - private static field
const button = new ButtonToggle();
button.toggle();

科学检查私有变量的方式

正如我们在上面的例子中看到的,如果我们尝试访问类之外的私有字段,它将抛出异常并且不会像访问公共字段那样返回 undefined。💡

我们可以在类中使用try/catch来检查字段是否存在,如下代码所示:

javascript">class ButtonToggle extends HTMLElement {

   // initialised as null
    #value = null;

    get #getValue(){
        if(!this.#value){
            throw new Error('no value');
        } 
        return this.#value
    }

    static isButtonToggle(obj){
        try {
            obj.#getValue;
            return true;
        } catch {
            // could be an error internal to the getter
            return false; 
        }
    }

}

在上面的代码中,我们通过在isButtonToggle方法中加上try/catch来捕获当getValue不存在时的异常。但这样实现会在实际应用中遇到一个问题:try/catch中往往还有其它代码逻辑,当异常发生时,开发人员无法判断是由于属性不存在或者仅仅只是其它的异常。因此,ES2022提供了一个更加科学的方式来应对这种情况。可以来看下面的例子:

javascript">class ButtonToggle extends HTMLElement {

   // initialised as null
    value = null;

    get #getValue(){
        if(!this.#value){
            throw new Error('no value');
        } 
        return this.#value;
    }

    static isButtonToggle(obj){
       return #value in obj && #getValue in obj
    }

}

类静态代码块

这里其实原文说了很多,我个人觉得弄复杂了。简单来讲,就是可以在类中直接用逻辑初始化静态属性。

javascript">class Translator {
  static translations = {
    yes: 'ja',
    no: 'nein',
    maybe: 'vielleicht',
  };
  static englishWords = [];
  static germanWords = [];
  static { // (A)
    for (const [english, german] of Object.entries(this.translations)) {
      this.englishWords.push(english);
      this.germanWords.push(german);
    }
  }
}

正则匹配返回下标

可以通过给正则表达式加上 d 字符来让返回的结果中带上匹配字符的开始下标和结束下标。我们来看一组返回的对比:

javascript">const fruits = 'Fruits: mango, mangosteen, orange'
const regex = /(mango)/g;

// .exec
RegExp(regex).exec(fruits);
// [
//   'mango',
//   index: 8,
//   input: 'Fruits: mango, mangosteen, orange',
//   groups: undefined
// ]

// matchAll
const matches = [...fruits.matchAll(regex)];
matches[0];
// [
//   'mango',
//   'mango',
//   index: 8,
//   input: 'Fruits: mango, mangosteen, orange',
//   groups: undefined
// ]

vs

javascript">const fruits = 'Fruits: mango, mangosteen, orange'
// /gd instead of the previous /g
const regex = /(mango)/gd;

const matches = [...fruits.matchAll(regex)];
matches[0];

// [
// "mango",
// "mango",
// groups: undefined
// index: 8
// indices:[]
//  [8, 13],
//  [8, 13]
// ]
// groups: undefined

可以看到加了 d 字符后,返回结果中多了indices字段,里面包含了命中的下标数组。

在async外部使用await

在这之前,await只能在async方法中使用。在ES2022的标准中,可以在async方法之外使用await。例如,我们可以推迟一个模块及其父模块的执行,直到导入其它内容。

这在一些场景中非常有用,例如你需要引入一个动态路径的资源:

javascript">// we need to get the appropriate translation keys based on the language
const translationKeys = await import(`/i18n/${navigator.language}`);

或者想要在一些资源引入失败时,替换成其它资源:

javascript">let jQuery;
try {
  jQuery = await import('https://cdn-a.com/jQuery');
} catch {
  jQuery = await import('https://cdn-b.com/jQuery');
}

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

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

javascript">const arr = [10,20,30,40];

// same -> 10
arr[1];
arr.at(1);

// same -> 40
arr[arr.length -1];
arr.at(-1);

Object.hasOwn(object, property)

在JavaScript我们已经有了Object.prototype.hasOwnProperty但是,正如MDN文档所指出的,最好不要使用hasOwnProperty在原型本身之外,因为它不是受保护的属性,这意味着object可以叫它的财产hasOwnProperty与此无关Object.prototype.hasOwnProperty
简单讲就是使用Object.hasOwn来替代Object.prototype.hasOwnProperty.call(太长了,不好看)🤣,可以来看下面的例子:

javascript">const obj = {
    hasOwnProperty:()=> {
        return false
    }
}

obj.hasOwnProperty('prop'); // false

如您所见,我们定义了自己的方法hasOwnProperty,它覆盖了原型上的问题,这个问题不存在于Object.hasOwn()。🤐

Object.hasOwn()拿走我们的Object作为第一个参数和我们要检查的第二个属性:

javascript">const student = {
    name: 'Mark',
    age: 18
}

Object.hasOwn(student,'age'); // true
Object.hasOwn(student,'grade'); // false

是不是感觉ES13 新特性不少呀🤔?
请添加图片描述


http://www.niftyadmin.cn/n/805824.html

相关文章

【Redis实现系列】RedisDB实现

RedisDB 核心实现 概述 Redis 服务器将所有数据库都保存在服务器状态 redis.h/redisServer 结构的 db 数组中,db 数组的每个项都是一个 redis.h/redisDb 结构,每个redisDb结构代表一个数据库。 定义: struct redisServer {// ...// 一个…

Javascript技术实现真正的网上试听 (转)

Javascript技术实现真正的网上试听 (转)[more]Javascript技术实现真正的网上试听-(样本)http://www.ue100.com/GRZY/yiiy/music/AgainstAllOdds.htm 归于yiiy eMail:yiiyinfoworld.sh.cn 描述:欢迎使用本脚本.本脚本使用户在线收听音乐的同时…

【Redis实现系列】过期键处理

过期键处理 过期键的判定 通过过期字典,程序可以用以下步骤检查一个给定键是否过期: 检查给定键是否存在于过期字典:如果存在,那么取得键的过期时间。 检查当前UNIX时间戳是否大于键的过期时间:如果是的话&#xff…

谈谈服务端渲染技术NuxtJS

📒博客首页:酸狗的博客🍋 🎉欢迎关注🔎点赞👍收藏⭐️留言📝 💖热爱前端学习,期待一起交流!✨ 🙏作者水平很有限,如果发现错误&#x…

在C + + Builder 中 显 示 透 明 位 图 (转)

在C + + Builder 中 显 示 透 明 位 图 (转)[more]在C + + Builder 中显 示 透 明 位 图我 们 知 道,GIF 类 型 的 图 像 格 式 支 持 透 明 显 示, 而BMP 类 型 的 图 像 格 式 不 支 持 透 明 显 示。 在…

ssh远程连接到指定用户

两种方式: 1. ssh IP -l 用户名 2. ssh 用户名IP 利用ssh客户端连接远端服务器: ssh rootip -p 22 ----》 回车 输入密码

家人问你还没有对象怎么办?那你new一个对象呀

📒博客首页:酸狗的博客🍋 🎉欢迎关注🔎点赞👍收藏⭐️留言📝 💖热爱前端学习,期待一起交流!✨ 🙏作者水平很有限,如果发现错误&#x…

【Redis实现系列】持久化RDB实现

RDB RDB持久化既可以手动执行,也可以根据服务器配置选项定期执行,该功能可以将某个时间点上的数据库状态保存到一个RDB文件中。 RDB持久化功能所生成的RDB文件是一个经过压缩的二进制文件,通过该文件可以还原生成RDB文件时的数据库状态。 …