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

x33g5p2x  于2022-07-14 转载在 Java  
字(9.0k)|赞(0)|评价(0)|浏览(574)

因为ES6的内容太多了, 如果想学ES6的新特性, 那么可以看 http://t.csdn.cn/1bXjB 超级全, 吐血编写

ES7

includes() 数组中是否包含

includes() 方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回 false。 使用 includes() 判断字符串和字符时是区分大小写的
语法:
arr.includes(searchElement)
arr.includes(searchElement, fromIndex)

  • element:要查找的元素
  • start:开始查找的位置。
  • 返回值: 如果数组中包含要查找的元素,则返回true,否则返回false。
  • 如果start参数小于0,则重置为0,如果start参数大于等于数组长度,则返回false。
  1. [1,2,3].includes(2); // true
  2. [1,2,3].includes(2, 0); // true
  3. [1,2,3].includes(2, 2); // false
  4. [1,2,3].includes(2, 5); // false
  5. [1,2,3].includes(2, -1); // false

该方法与indexOf()的区别在于,indexOf()不会识别NaN和稀疏数组中的缺失元素。而includes()方法可以。

  1. var array = [1,2,3];
  2. array.length = 5;
  3. array.push(NaN);
  4. array.push(undefined);
  5. array.push("");
  6. console.log( array.includes(undefined))// true
  7. console.log( array.includes(NaN)) // true
  8. console.log( array.includes("")) // true
  9. console.log(array.indexOf(undefined))// 6
  10. console.log(array.indexOf(NaN))// -1
  11. console.log(array.indexOf(""))// 7

指数运算符**

在ES7中引入了指数运算符,具有与Math.pow()求幂运算 等效的计算结果

  1. console.log(2**10);// 输出1024
  2. console.log(Math.pow(2, 10)) // 输出1024

ES8

Async/Await

我们都知道使用Promise能很好地解决回调地狱的问题,但如果处理流程比较复杂的话,那么整段代码将充斥着then,语义化不明显,代码不能很好地表示执行流程,那有没有比Promise更优雅的异步方式? ES7提出的基于Promise的解决异步的最终方案Async/Await

async

async是一个加在函数前的修饰符,被async定义的函数会默认返回一个Promise对象resolve的值。因此对async修饰的函数可以直接使用then方法, 如果方法出现了异常,那么会调用catch ,注意被async修饰的方法会变为异步方法

  1. async function fun0(){
  2. console.log(1);
  3. return 1;
  4. }
  5. fun0().then(val=>{
  6. console.log(val) // 1,1
  7. }).catch(err=>{
  8. console.log(err)
  9. })
  10. async function fun1(){
  11. console.log('Promise');
  12. return new Promise(function(resolve,reject){
  13. resolve('Promise1')
  14. })
  15. }
  16. fun1().then(val => {
  17. console.log(val); // Promise Promise
  18. })
  19. async function fun2(){
  20. throw new Error("xxxxx")
  21. }
  22. fun2().then(val=>{
  23. console.log(val)
  24. }).catch(err=>{
  25. console.log(err) //xxxxx
  26. })
await

await 也是一个修饰符,只能放在async定义的函数内。可以理解为等待 , await 修饰的如果是Promise对象:可以获取Promise中返回的内容(resolve或reject的参数),且取到值后语句才会往下执行;如果不是Promise对象,比如字符串那么会把这个字符串当做await表达式的结果

使用await必须是直系(作用域链不能隔代),这样会报错:Uncaught SyntaxError: await is only valid in async function。,比如下面

  1. let data = 'data'
  2. demo = async function () {
  3. const test = function () {
  4. await data //错误使用
  5. }
  6. }

注意只有 let c = await new Promise ,配合才能进行等待内部执行结果,如果不是和Promise 进行配合那么await 等于无效

  1. const demo = async ()=>{
  2. let result = await setTimeout(()=>{
  3. console.log('我延迟了一秒');
  4. }, 1000)
  5. console.log('======================');
  6. }
  7. demo()
  8. // 执行结果
  9. //======================
  10. //我延迟了一秒
  11. //奇怪,并没有await啊?setTimeout是异步啊,问题在哪?问题就在于setTimeout这是个异步,但是不是Promise!起不到“等待一会”的作用。
  12. //请记住await是在等待一个Promise的异步返回

混合使用async 和await 案例

  1. async function fun(){
  2. let a = 1;
  3. //内部使用了ajax会异步, 我们在外部使用await等待内部请求的结果
  4. let b = await new Promise((resolve,reject)=>{
  5. var ajax = new XMLHttpRequest();
  6. ajax.open("GET", "http://localhost:7003/test/haoxiaoxiao");
  7. ajax.setRequestHeader("Content-Type", "application/json");
  8. ajax.send({
  9. "userName": "卢超glrau",
  10. "passWord": "Y2hKz0h",
  11. "phone": "18110454396",
  12. "email": "h.whf@gjifcniah.dk"
  13. });
  14. ajax.onreadystatechange = function () {
  15. if (ajax.readyState == 4 && ajax.status == 200) {
  16. var json = JSON.parse(ajax.responseText);
  17. console.log(json)
  18. resolve(json);
  19. }
  20. }
  21. })
  22. //内部使用了setTimeout会异步, 我们在外部使用await等待setTimeout内部的结果
  23. let c = await new Promise((resolve, reject) => {
  24. setTimeout(()=>{
  25. resolve('Promise')
  26. }, 1000)
  27. });
  28. let d = await function(){
  29. return 'function'
  30. }()
  31. console.log(a,b,c,d)
  32. return b;
  33. }
  34. fun();
async/await 优势实战
  1. const setDelay = (millisecond) => {
  2. return new Promise((resolve, reject)=>{
  3. if (typeof millisecond != 'number') reject(new Error('参数必须是number类型'));
  4. setTimeout(()=> {
  5. resolve(`我延迟了${millisecond}毫秒后输出的`)
  6. }, millisecond)
  7. })
  8. }
  9. const setDelaySecond = (seconds) => {
  10. return new Promise((resolve, reject)=>{
  11. if (typeof seconds != 'number' || seconds > 10) reject(new Error('参数必须是number类型,并且小于等于10'));
  12. setTimeout(()=> {
  13. resolve(`我延迟了${seconds}秒后输出的,注意单位是秒`)
  14. }, seconds * 1000)
  15. })
  16. }

比如上面两个延时函数(写在上面),比如我想先延时1秒,在延迟2秒,再延时1秒,最后输出“完成”,这个过程,如果用then的写法,大概是这样:

  1. setDelay(1000)
  2. .then(result=>{
  3. console.log(result);
  4. return setDelaySecond(2) //注意
  5. })
  6. .then(result=>{
  7. console.log(result);
  8. return setDelay(1000) //注意
  9. })
  10. .then(result=>{
  11. console.log(result);
  12. console.log('完成')
  13. })
  14. .catch(err=>{
  15. console.log(err);
  16. })

咋一看是不是挺繁琐的?如果逻辑多了估计看得更累,现在我们来试一下async/await

  1. (async ()=>{
  2. const result = await setDelay(1000);
  3. console.log(result);
  4. console.log(await setDelaySecond(2));
  5. console.log(await setDelay(1000));
  6. console.log('完成了');
  7. })()

看!是不是没有冗余的长长的链式代码,语义化也非常清楚,非常舒服,那么你看到这里,一定还发现了,上面的catch我们是不是没有在async中实现?接下去我们就分析一下async/await如何处理错误?

async/await错误处理

因为async函数返回的是一个Promise,所以我们可以在外面catch住错误。

  1. (async ()=>{
  2. const result = await setDelay(1000);
  3. console.log(result);
  4. console.log(await setDelaySecond(2));
  5. console.log(await setDelay(1000));
  6. console.log('完成了');
  7. })().catch(err=>{
  8. console.log(err)
  9. })
  10. // 下面这种也行
  11. const demo = async ()=>{
  12. const result = await setDelay(1000);
  13. console.log(result);
  14. console.log(await setDelaySecond(2));
  15. console.log(await setDelay(1000));
  16. console.log('完成了');
  17. }
  18. demo().catch(err=>{
  19. console.log(err);
  20. })

在async函数的catch中捕获错误,当做一个Pormise处理,同时你不想用这种方法,可以使用try…catch语句:

  1. (async ()=>{
  2. try{
  3. const result = await setDelay(1000);
  4. console.log(result);
  5. console.log(await setDelaySecond(2));
  6. console.log(await setDelay(1000));
  7. console.log('完成了');
  8. } catch (e) {
  9. console.log(e); // 这里捕获错误
  10. }
  11. })()

这时候你就不需要在外面catch了。有人会问了,我try…catch好像只能包裹代码块,如果我需要拆分开分别处理,不想因为一个的错误就整个process都crash掉了,那么难道我要写一堆try…catch吗?我就是别扭,我就是不想写try…catch怎嘛办? 我们知道await后面跟着的肯定是一个Promise那是不是可以这样写?

  1. (async ()=>{
  2. const result = await setDelay(1000).catch(err=>{
  3. console.log(err)
  4. });
  5. console.log(result);
  6. const result1 = await setDelaySecond(12).catch(err=>{
  7. console.log(err)
  8. })
  9. console.log(result1);
  10. console.log(await setDelay(1000));
  11. console.log('完成了');
  12. })()

是不是就算有错误,也不会影响后续的操作,是不是很棒?当然不是,你说这代码也忒丑了吧,乱七八糟的,写得别扭await又跟着catch。那么我们可以改进一下,封装一下提取错误的代码函数:

  1. function to(promise) {
  2. return promise.then(data => {
  3. return [null, data];
  4. })
  5. .catch(err => [err]); // es6的返回写法
  6. }
  7. // 返回的是一个数组,第一个是错误,第二个是异步结果,使用如下:
  8. (async ()=>{
  9. // es6的写法,返回一个数组(你可以改回es5的写法觉得不习惯的话),第一个是错误信息,第二个是then的异步返回数据,这里要注意一下重复变量声明可能导致问题(这里举例是全局,如果用let,const,请换变量名)。
  10. [err, result] = await to(setDelay(1000))
  11. // 如果err存在就是有错,不想继续执行就抛出错误
  12. if (err) throw new Error('出现错误,同时我不想执行了');
  13. console.log(result);
  14. [err, result1] = await to(setDelaySecond(12))
  15. // 还想执行就不要抛出错误
  16. if (err) console.log('出现错误,同时我想继续执行', err);
  17. console.log(result1);
  18. console.log(await setDelay(1000));
  19. console.log('完成了');
  20. })()
async/await的中断(终止程序)

写在async/await中想要中断程序就很简单了,因为语义化非常明显,其实就和一般的function写法一样,想要中断的时候,直接return一个值就行,null,空,false都是可以的。看例子:

  1. let count = 6;
  2. const demo = async ()=>{
  3. const result = await setDelay(1000);
  4. console.log(result);
  5. const result1 = await setDelaySecond(count);
  6. console.log(result1);
  7. if (count > 5) {
  8. return '我退出了,下面的不进行了';
  9. // return;
  10. // return false; // 这些写法都可以
  11. // return null;
  12. }
  13. console.log(await setDelay(1000));
  14. console.log('完成了');
  15. };
  16. demo().then(result=>{
  17. console.log(result);
  18. })
  19. .catch(err=>{
  20. console.log(err);
  21. })

Object.values(),Object.entries()

ES5 引入了Object.keys方法,返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名。ES8引入了跟Object.keys配套的Object.values和Object.entries,作为遍历一个对象的补充手段,供for…of循环使用。

Object.values()

  1. //假设我们要遍历如下对象obj的所有值:
  2. const obj = {a: 1, b: 2, c: 3};
  3. //不使用Object.values() :ES7
  4. const vals=Object.keys(obj).map(key=>obj[key]);
  5. console.log(vals);//[1, 2, 3]
  6. //使用Object.values() :ES8
  7. const values=Object.values(obj1);
  8. console.log(values);//[1, 2, 3]

Object.entries()

  1. //不使用Object.entries() :ES7
  2. Object.keys(obj).forEach(key=>{
  3. console.log('key:'+key+' value:'+obj[key]);
  4. })
  5. //key:a value:1
  6. //key:b value:2
  7. //key:c value:3
  8. //使用Object.entries() :ES8
  9. for(let [key,value] of Object.entries(obj1)){
  10. console.log(`key: ${key} value:${value}`)
  11. }
  12. //key:a value:1
  13. //key:b value:2
  14. //key:c value:3

String padding

在ES8中String 新增了两个实例函数 String.prototype.padStart 和 String.prototype.padEnd,允许将空字符串或其他字符串添加到原始字符串的开头或结尾。
ES5对String补白的方式, 例如将数字都输出成两位数,前面0补位学习

  1. for(let i = 1 ; i < 32 ; i++){
  2. console.log(i >= 10 ? i : `0${i}`)
  3. }
  4. // 1-9输出01-09
  5. // 10-31正常输出

padStart
用另外一个字符串填充当前字符串(若是须要的话,会重复屡次),从头补白(也就是左侧)

  • 第一个参数是目标长度,要输出的位数
  • 第二个参数是占位内容,默认是空格
  • 返回值是生成的新的字符串
  1. for(let i = 1 ; i < 32 ; i++){
  2. // 目标是2位数,不够的用0补齐
  3. console.log(i.toString().padStart(2, '0'))
  4. }
  5. // 1-9输出01-09
  6. // 10-31正常输出

padEnd
用另外一个字符串填充当前字符串(若是须要的话,会重复屡次),从当前字符串的末尾(右侧)开始填充

  • 第一个参数是目标长度,要输出的位数
  • 第二个参数是占位内容,默认是空格
  • 返回值是生成的新的字符串
  1. for(let i = 1 ; i <= 100 ; i++){
  2. // 从尾部补充到指定的长度
  3. console.log(i.toString().padEnd(3, 'xx'))
  4. }
  5. //1xx
  6. //11x
  7. //100

函数参数列表结尾允许逗号

重新排列项目更简单,不必添加和删除逗号,最后的逗号了js自动处理。

  1. //定义参数时
  2. function foo(
  3. param1,
  4. param2,//结尾逗号
  5. ) {}
  6. //传参时
  7. foo(
  8. 'coffe',
  9. '1891',//结尾逗号
  10. );
  11. //对象中
  12. let obj = {
  13. "a": 'coffe',
  14. "b": '1891',//结尾逗号
  15. };
  16. //数组中
  17. let arr = [
  18. 'coffe',
  19. '1891',//结尾逗号
  20. ];

Object.getOwnPropertyDescriptors()

获取所有属性里面的数据描述符,只接受一个参数,目标对象。

  1. console.log(Object.getOwnPropertyDescriptors(data))
  2. // Portland: {value: "78/50", writable: true, enumerable: true, configurable: true}
  3. // Dublin: {value: "88/52", writable: true, enumerable: true, configurable: true}
  4. // Lima: {value: "58/40", writable: false, enumerable: false, configurable: true}

获取单个属性的描述符 Object.getOwnPropertyDescriptor() 这个方法接收两个参数:属性所在的对象和要读取其描述符的属性名称。

返回值是一个对象:

  • 如果是访问器属性,这个对象的属性有configurable、enumerable、get和set;
  • 如果是数据属性,这个对象的属性有configurable、enumerable、writable和value。

SharedArrayBuffer对象

使用SharedArrayBuffer,两个线程的两个WebWorker都可以在同一块内存中写入数据和读取数据。这意味着它们不像postMessage那样具有通信开销和延迟。两个Web工作人员都可以立即访问到需要的数据。但是,同时从两个线程同时访问存在一定的危险。它可能导致内存中出现竞争状况。 现在游览器都禁用了SharedArrayBuffer,

Atomics对象

Atomics 对象提供了一组静态方法用来对 SharedArrayBuffer 对象进行原子操作。

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

相关文章