数据类型
最新的 ECMAScript 标准定义了8种数据类型。
基础类型:Number, String, Boolean, undefined, null, Symbol(ES6新增), BigInt(ES10新增)
复杂类型:Object
特别注意
-
Symbol,表示独一无二的值。Symbol 值通过
Symbol()函数生成。 Symbol 类型的作用是,表示数据为独一无二的,可以保证不会与其他属性名产生冲突。Symbol函数前不能使用new命令,否则会报错。因为symbol是原始数据类型。 -
Bigint是用来安全地存储和操作大整数,且可以超过数字的安全整数限制。BigInt,是通过在整数末尾附加n或调用构造函数来创建的。BigInt,不能与数字互换操作。 -
Object包括:Array、function、Set、Map、WeakMap、WeakSet、RegExp、Date、Math…(instanceof Object返回都为true)
JavaScript执行机制(Event-Loop)
Javascript是一门单线程语言,只有前一个任务执行完毕才会运行下一个任务
所以为了规避掉资源分配的浪费,这就需要任务队列和事件循环
任务队列
任务队列:是一种数据结构,存放要执行的任务。然后事件循环系统再以先进先出原则按顺序执行队列中的任务。
为了处理高优先级的任务,和解决单任务执行过长的问题:
所以将任务划分:同步和异步;异步任务里又被分为:微任务和宏任务
同步和异步
同步任务:会一个一个立即执行的任务
异步任务:需要一段时间才能返回,不会立即执行的任务
微任务和宏任务
JavaScript执行时,浏览器V8引擎会在内部创建一个微任务队列和宏任务队列
宏任务执行过程中,如果有新的微任务产生,就添加到微任务队列中
当前宏任务里的微任务全部执行完,才会执行下一个宏任务
微任务包括: promise.then、MutationObserver(监听DOM)、node 中的 process.nextTick等
宏任务包括: 渲染事件、请求、script、setTimeout、setInterval、Node中的setImmediate、I/O 等
事件循环
简单一句话概括可以为:一个宏任务,所有微任务,渲染,一个宏任务,所有微任务,渲染.....
- 所有同步任务都在主线程上依次执行,形成一个执行栈(调用栈),异步任务处理完后则放入一个任务队列
- 当执行栈中任务执行完,再去检查微任务队列里的微任务是否为空,有就执行,如果执行微任务过程中又遇到微任务,就添加到微任务队列末尾继续执行,把微任务全部执行完
- 微任务执行完后,有需要的话会渲染页面,再到任务队列检查宏任务是否为空,有就取出最先进入队列的宏任务压入执行栈中执行其同步代码
- 然后回到第2步执行该宏任务中的微任务,如此反复,直到宏任务也执行完,如此循环
async / await
async/await 是 ES7 引入的重大改进的地方,可以在不阻塞主线程的情况下,使用同步代码实现异步访问资源的能力
function bar () {
console.log(2)
}
async function fun() {
console.log(1)
await bar()
console.log(3)
}
console.log(4)
fun()
console.log(5)
输出结果:4 1 2 5 3
因为await的意思就是等,等await后面的执行完。所以await bar(),是从右向左执行,执行完bar(),然后遇到await,返回一个微任务(哪怕这任务里没东西),放到微任务队列让出主线程。
上面说了 async/await 就是把异步以同步的形式实现,同步就是一步一步一行一行来嘛,await在微任务队列里都没回来,那在await下面的自然不能执行,导致 3 最后打印
完成下面题目
答案我就不写啦,留给你们自行思考~~~
console.log('start')
async function async1() {
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2 end')
}
async1()
setTimeout(function () {
console.log('setTimeout')
}, 0)
new Promise(resolve => {
console.log('Promise1')
resolve()
})
.then(function () {
console.log('promise2')
})
.then(function () {
console.log('promise3')
})
console.log('end')
进阶:
const myPromise = Promise.resolve(Promise.resolve('Promise'));
function funcOne() {
setTimeout(() => console.log('Timeout 1!'), 0);
myPromise.then(res => res).then(res => console.log(`${res} 1!`));
console.log('Last line 1!');
}
async function funcTwo() {
const res = await myPromise;
console.log(`${res} 2!`)
setTimeout(() => console.log('Timeout 2!'), 0);
console.log('Last line 2!');
}
funcOne();
funcTwo();