星光不问赶路人,时光不负有心人。 加油!
前端面试 - JS总结(1) - 基础 (数据类型, 事件与函数, 原型链)
前端面试 - JS总结(2) - ES6 (let, 箭头函数, this)
目录
一、异步
1. 异步概念
javascript语言是一门“单线程”的语言。所谓单线程,是指在JS引擎中负责解释和执行JavaScript代码的线程只有一个。 作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题 。
Javascript语言将任务的执行模式分成两种:同步(Synchronous)和异步(Asynchronous)。同步和异步区别:异步是基于JS单线程语言;异步不会阻塞代码执行;同步会阻塞代码执行.
在JS中,异步编程只有四种情况:( 网络请求,如Ajax图片加载; 定时任务,如setTimeout)
- –> 定时器都是异步编程的
- –> 所有的事件绑定都是异步编程的
- –> Ajax读取数据都是异步编程的,我们一般设置为异步编程
- –> 回调函数都是异步编程的
2. 异步机制
具体来说,异步运行机制如下:
(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。(事件就是回调函数,用于触发函数的执行)。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步。
只要主线程空了,就会去读取"任务队列",这就是JavaScript的运行机制。这个过程会不断重复。
3. 宏任务和微任务
宏任务(macrotask )和微任务(microtask )表示异步任务的两种分类。在挂起任务时,JS 引擎会将所有任务按照类别分到这两个队列中,首先在 macrotask 的队列(这个队列也被叫做 task queue)中取出第一个任务,执行完毕后取出 microtask 队列中的所有任务顺序执行;之后再取 macrotask 任务,周而复始,直至两个队列的任务都取完。同一次事件循环中 微任务永远在宏任务之前执行
参考链接:https://www.cnblogs.com/ckAng/p/11133643.html
4. JS常见的异步模式
(1)回调函数 -- 回调函数作为参数传递给另一个函数,在另一个函数中被调用。但是使用回调函数,经常会写出回调地狱,这是非常致命的。回调地狱的根本问题是:嵌套函数存在耦合性; 嵌套函数变多,处理问题的困难也变大
(2)事件监听 -- 事件监听模式,异步任务的执行取决于,某个事件的发生。比如点击事件(onClick)和内容改变时间(onChange)等
(3)发布/订阅模式 -- 想象有一个类似消息中心的地方,可以在消息中心“注册”一条消息,然后就会有若干对这消息感兴趣的人“订阅”,一旦该消息被“发布”,所有”订阅“了该消息的用户都会得到提醒。
(4)promise -- Promise是ES6推出的一种解决异步编程的解决方案。有三种状态:等待中(pending)、完成(resolved)、拒绝(rejected)。一旦状态从等待改变为其他状态就不再可变了。Promise是个构造函数,接受一个函数作为参数。作为参数的函数有两个参数:resolve和reject,分别对应完成和拒绝两种状态。我们可以选择在不同时候执行resolve或reject去触发下一个动作,执行then方法里的函数。Promise实现了链式调用,每次调用then之后返回的都是一个Promise对象。
(5)Generator(ES6) -- Generator 最大的特点就是可以控制函数的执行。Generator 函数调用和普通函数不同,它会返回一个迭代器
(6)async/await(ES7) -- 一个函数如果加上async,那么该函数就会返回一个Promise对象。async函数执行后可以继续使用then等方法来继续执行后面的逻辑。async函数执行遇到await后,等待后面的Promise对象的状态从pending变成resolve后,将resolve的参数返回并自动往下执行知道下一个await或结束。
参考链接:https://www.cnblogs.com/bzsheng/p/12456944.html
5. 回调函数(Callback)
回调函数是一段可执行的代码段,它作为一个参数传递给其他的代码,其作用是在需要的时候方便调用这段(回调函数)代码
回调地狱的根本问题就是:
- 嵌套函数存在耦合性,一旦有所改动,就会牵一发而动全身
- 嵌套函数一多,就很难处理错误
当然,回调函数还存在着别的几个缺点,比如不能使用 try catch 捕获错误,不能直接 return。