JavaScript-ES9~ES10新特性使用教程

x33g5p2x  于2022-07-19 转载在 Java  
字(6.6k)|赞(0)|评价(0)|浏览(402)

JavaScript-ES7~ES8新特性使用教程

ES9

await for…of

await可以和for…的循环使用,以某种方式运行异步操作

const fruitBasket = {
        apple: 27,
        grape: 0,
        pear: 14
    };
    const getNumFruit = fruit => {
        return fruitBasket[fruit];
    };

    // 模拟异步从服务器获取数据
    const sleep = ms => {
        return new Promise(resolve => setTimeout(resolve, ms))
    }
    const getNumFruie = fruit => {
        return sleep(1000).then(v => fruitBasket[fruit]);
    };



    const control = async _ => {
        console.log('Start')

        const numApples = await getNumFruit('apple');
        console.log(numApples);

        const numGrapes = await getNumFruit('grape');
        console.log(numGrapes);

        const numPears = await getNumFruit('pear');
        console.log(numPears);

        console.log('End')
    }
    control();



    //现在假设有一个数组,
    const fruitsToGet = ["apple", "grape", "pear"];

    const forLoop = async _ => {
        console.log('start');
        for (let index = 0; index < fruitsToGet.length; index ++) {
            const fruit = fruitsToGet[index];
            const numFruit = await getNumFruit(fruit);
            console.log(numFruit);
        }
        console.log('End')
    }

    //在es9中可以await可以和for...of循环一起使用, 注意不是for i 和for in 来进行等待
    const forof = async _ => {
        console.log('start');
        for await (let string of fruitsToGet) {
            const numFruit =  getNumFruit(string);
            console.log(numFruit);
        }
        console.log('End')
    }

Promise.finally()

finally方法的回调函数不接受任何参数,这意味着没有办法知道,前面的 Promise 状态到底是fulfilled还是rejected。这表明,finally方法里面的操作,应该是与状态无关的,不依赖于 Promise 的执行结果。finally本质上是then方法的特例。

finally方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。一般用于释放一些资源的

new Promise((resolve, reject) =>{
        
    } ).then((ref)=>{
        
    }).catch(err=>{
        
    }).finally(()=>{
        //无论结果如何,最终都会执行
    })

Rest 属性

rest和Spread都是三个... 在es6中Spread是将数组对象等合并追加,而在ES9中还可以将数组和对象进行拆解,当我们在代码中看到 “…” 时,它要么是 rest 参数,要么是 spread 语法。

有一个简单的方法可以区分它们:

  • 若 … 出现在函数参数列表的最后,那么它就是 rest 参数,它会把参数列表中剩余的参数收集到一个数组中。
  • 若 … 出现在函数调用或类似的表达式中,那它就是 spread 语法,它会把一个数组展开为列表。

使用场景:

  • Rest 参数用于创建可接受任意数量参数的函数。
  • Spread 语法用于将数组传递给通常需要含有许多参数的函数。
  • 我们可以使用这两种语法轻松地互相转换列表与参数数组。

旧式的 arguments(类数组且可迭代的对象)也依然能够帮助我们获取函数调用中的所有参数。

// Rest 方式

let arr = [3, 5, 1];
function f(...arr) {
    console.log(arr) //[3, 5, 1]
}
f(...arr)

console.log(...[1, 2, 3]) // 1 2 3
console.log([...[1,2,3], 4]) // [1, 2, 3, 4]

// Spread  方式

let arr1 = [1, -2, 3, 4];
let arr2 = [8, 3, -8, 1];

alert( Math.max(...arr1, ...arr2) ); // 8
alert( Math.max(1, ...arr1, 2, ...arr2, 25) ); // 25

let arr = [3, 5, 1];
let arr2 = [8, 9, 15];
let merged = [0, ...arr, 2, ...arr2];
alert(merged); // 0,3,5,1,2,8,9,15  

let arr = [1, 2, 3];
let arrCopy = [...arr]; // 将数组参数结果放到一个新数组

let obj = { a: 1, b: 2, c: 3 };
let objCopy = { ...obj }; // 将对象参数返回到一个新对象

正则表达式命名捕获组

ES9之前是这样的

const re = /(\d{4})-(\d{2})-(\d{2})/
const match= re.exec('2021-07-12')
console.log(match[0]) //  2021-07-12
console.log(match[1]) //  2021
console.log(match[2]) //  07
console.log(match[3]) //  12

ES9 引入了命名捕获组,允许为每一个组匹配指定一个名字,既便于阅读代码,又便于引用
语法: (?P<name>Expression)

const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
const match = re.exec('2021-07-12')
console.log(match.groups) //  {year: "2021", month: "07", day: "12"}
console.log(match.groups.year) // 2021
console.log(match.groups.month) //  07
console.log(match.groups.day) //  12

正则表达式反向断言

首先要了解组group的概念,用()包含的是组,里面的数据会获取供以后使用,这叫获取匹配,通过Match.group(index)获取,第一个group从1开始,index=0表示获取整个匹配字符串。正向表示匹配前面,反向表示匹配后面。

  • (?=pattern):正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
  • (?=pattern):正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。
  • (?<=pattern): 反向肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。
  • (?<!pattern):反向否定预查,与正向否定预查类似,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。

正则表达式dotAll模式

正则表达式中点.匹配除回车外的任何单字符,标记s改变这种行为,允许行终止符的出现,例如:

/hello.world/.test('hello\nworld');  // false
/hello.world/s.test('hello\nworld'); // true

正则表达式 Unicode 转义

到目前为止,在正则表达式中本地访问 Unicode 字符属性是不被允许的。ES2018添加了 Unicode 属性转义——形式为\p{...}\P{...},在正则表达式中使用标记 u (unicode) 设置,在\p块儿内,可以以键值对的方式设置需要匹配的属性而非具体内容。例如:

const reGreekSymbol = /\p{Script=Greek}/u;
reGreekSymbol.test('π'); // true

这个特性可以避免使用特定 Unicode 区间来进行内容类型判断,提升可读性和可维护性。

ES10

Array.flat()和Array.flatMap() 数组展平

Array.flat()把数组展平,通过传入层级深度参数(默认为1),来为下层数组提升层级。

[1, 2, [3, 4]].flat();
// [ 1, 2, 3, 4 ]
[1, 2, [3, 4, [5, 6]]].flat(2);
// [ 1, 2, 3, 4, 5, 6 ]

Array.prototype.flatMap() 它是Array.prototype.map() 和 Array.prototype.flat() 的组合,通过对map调整后的数据尝试展平操作

let arr= [1, 2, [3, 4]].flatMap(v => {
       console.log(v)
        if (typeof v === 'number') {
            return v * 2
        } else {
            return v.map(v => v * 2)
        }
    })
   console.log(arr)

String.trimStart()和String.trimEnd()去掉开头结尾空格文本

把头尾的空格文本去掉,来规避展示的不受控情况。自ES5来,String.prototype.trim() 被用于去除头尾上的空格、换行符等,现在通过 trimStart(),trimEnd() 来头和尾进行单独控制。trimLeft()、trimRight() 是他们的别名

const string = ' Hello ES2019! ';
string.trimStart();
// 'Hello ES2019! '
string.trimEnd();
// ' Hello ES2019!'

String.prototype.matchAll为所有匹配的匹配对象返回一个迭代器

matchAll()为所有匹配的匹配对象返回一个迭代器

const raw_arr = 'test1  test2  test3'.matchAll((/t(e)(st(\d?))/g));
const arr = [...raw_arr];

Symbol.prototype.description 只读属性,回 Symbol 对象的可选描述的字符串

Symbol 是ES6中引入的基本数据类型,可以用作对象属性的标识符。描述属性是只读的,可用于获取符号对象的描述,更好了解它的作用。

const symbol = Symbol('This is a Symbol');
symbol;
// Symbol(This is a Symbol)
Symbol.description;
// 'This is a Symbol'

Object.fromEntries()返回一个给定对象自身可枚举属性的键值对数组

我们知道ES8引入了Object.entries把一个对象转为[key, value]键值对的形式,可以运用于像 Map 这种结构中。凡事有来有回,Object.fromEntries()用于把键值对还原成对象结构。

const entries = [ ['foo', 'bar'] ];
const object = Object.fromEntries(entries);
// { foo: 'bar' }

可选 Catch

在进行try…catch错误处理过程中,如果没有给catch传参数的话,代码就会报错。有时候我们并不关心错误情况,如:

const isValidJSON = json => {
  try {
    JSON.parse(json);
    return true;
  } catch (unusedError) {
    // Unused error parameter
    return false;
  }
};

在新规范中,我们可以省略catch绑定的参数和括号,更加灵活啦。

const isValidJSON = json => {
  try {
    JSON.parse(json);
    return true;
  } catch {
    return false;
  }
};

JSON Superset 超集

之前如果JSON字符串中包含有行分隔符(\u2028) 和段落分隔符(\u2029),那么在解析过程中会报错。现在ES2019对它们提供了支持。

JSON.parse('"\u2028"');
// SyntaxError

// ES2019
JSON.parse('"\u2028"');
// ''

JSON.stringify() 加强格式转化

emoji的字符长度是多少?

JavaScript将emoji解释为两个字符的原因是:UTF-16将emojis表示为两个代理项的组合。我们的emoji用字符’\uD83D’和’\uDE0E’编码。但是如果试图单独编写这样一个字符,例如’\uD83D’,则会认为这是一个无效的文本字符串。在早期版本中,这些字符将替换为特殊字符:

JSON.stringify('\uD83D');
// '"�"'

现在在字符代码之前插入转义字符,结果仍是可读且有效的UTF-8/UTF-16代码:

JSON.stringify('\uD83D');
// '"\\ud83d"'

Array.prototype.sort() 更加稳定

之前,规范允许不稳定的排序算法,如快速排序。 现在所有主流浏览器都使用稳定的排序算法。实际上,这意味着如果我们有一个对象数组,并在给定的键上对它们进行排序,那么列表中的元素将保持相对于具有相同键的其他对象的位置。

let array = [
  {a: 1, b: 2},
  {a: 2, b: 2},
  {a: 1, b: 3},
  {a: 2, b: 4},
  {a: 5, b: 3}
];
array.sort((a, b) => a.a - b.a);
// [{a: 1, b: 2}, {a: 1, b: 3}...] / [{a: 1, b: 3}, {a: 1, b: 2}...]

Function.prototype.toString() 重新修订

从ES2019开始,Function.prototype.toString()将从头到尾返回源代码中的实际文本片段。这意味着还将返回注释、空格和语法详细信息。
function /* a comment */ foo() {} 之前,Function.prototype.toString()只会返回了函数的主体,但没有注释和空格

foo.toString();
// 'function foo() {}'

现在,函数返回的结果与编写的一致:

点赞 -收藏-关注-便于以后复习和收到最新内容有其他问题在评论区讨论-或者私信我-收到会在第一时间回复感谢,配合,希望我的努力对你有帮助^_^免责声明:本文部分素材来源于网络,版权归原创者所有,如存在文章/图片/音视频等使用不当的情况,请随时私信联系我。

相关文章