try…catch
try...catch
用来检测代码执行过程中出现的错误,并捕获错误(可以避免由于某个js错误造成页面渲染出错)- 实用程度:
1 | try{ |
1 | try { |
async/await
async/await
是ES8写入的JS标准我们使用
async
来定义一个异步函数,使用await
等待一个异步的执行结果(准确说await
等待一个Promise
对象。await
必须在async function
内部使用),async
隐式的返回一个Promise
;(官方描述:async function
用来定义一个返回AsyncFunction
对象的异步函数。异步函数是指通过事件循环异步执行的函数,它会通过一个隐式的Promise
返回其结果。如果你在代码中使用了异步函数,就会发现它的语法和结构会更像是标准的同步函数。)实用程度:
重要程度:
async/await
可以让我们以更加优雅的姿势来写异步函数,或者说采用async/await
之后,我们就不需要再去考虑这个函数是不是异步的。在此之前,对于异步函数,我们必须等待异步函数执行完成之后,拿到异步函数的结果,才可以继续往下进行,基于此必须写深深的回调,在回调里拿结果,在回调里继续写异步…….俗称“回调地狱”。ES6的出现,带来了新的异步解决方案Promise
, 但Promise
真的是完美的吗?虽然我们确实走出了“回调地狱”,但相对的不过是把回调变成了纵向的,形成了一个纵向的回调链。异步编程的最高境界,就是应该让我们不用再去关心它是不是异步。async/await
的出现,就是让我们以同步的方式来编写异步代码。async/await
依赖于Promise
,是Generator
函数的语法糖。async/await
不会替换Promise
,但是好像可以替换Generator
,所以,Generator
就不讲了(我自己也不怎么用)
1 | // 使用 async 定义一个异步函数 |
1 | // 本来不想用延时器的,但实在没想到更适合的例子 |
如上代码,我们本意是想fn()
执行结束之后拿到返回值,将返回值给变量time
然后打印出time
,但由于fn()
内的setTimeout
是异步执行的,并不会等待 5秒等fn
执行完成之后再打印time
,所以造成的结果就是先打印time = undefined
,等了5秒后fn
才执行完。
但是这是我们理想的代码写法,虽然目前它没有按我们的理想执行,但使用async/await
之后,我们就可以使我们理想的代码按照我们的理想去执行。
结合Promise
去写理想代码
1 | const fn = () => { |
最佳实践应该是
try...catch
+async/await
+Promise
,三者结合写段代码
1 | const createPromise = () => { |
扩展运算符
即...
,用来将数组或者对象进行展开,也可以展开字符串,还可以在函数调用时对入参进行展开(描述不准确,看代码演示);(官方描述: 展开语法(Spread syntax), 可以在函数调用/数组构造时, 将数组表达式或者string在语法层面展开;还可以在构造字面量对象时, 将对象表达式按key-value的方式展开。)
- 常用来用来实现数组和对象的深拷贝
1 | /************************** 浅拷贝 ****************************/ |
我们本意是希望将numList1拷贝一份给numList2,然后对numList2进行修改,numList1我们可能在其他地方还需要用,但由于js对引用类型实行的时浅拷贝,所以会造成numList1也被改变,基于此,我们希望numList2改变不会影响numList1,我们就需要对numList1进行深拷贝
1 | /************************** map深拷贝 ****************************/ |
- 对象深拷贝
1 | const obj1 = {name: '李白'}; |
对于以上写法,如果
obj2
中的属性在obj1
中已经存在了,则obj2
中的属性会覆盖obj1
中的属性;后覆盖前以上写法也是刻意为之,对象深拷贝还有其他API
- 字符串扩展运算符和在函数调用时
1 | console.log(...'qasxxxxxdrrrrrrrfgbbbhuuuujmmmmko'); |