1.浏览器事件循环
当宏任务执行完毕后,会先清空微任务,微任务执行完毕后,再去执行宏任务(只拿出一个来执行)执行完后再去清空微任务,依次循环~~
vo js中全局对象都在VO中 vo可以代理global上的属性
AO 每个函数执行的时候 会将vo -> AO 并将上级作用域链和AO对象连接
宏任务:ui渲染线程,script脚本,setTimeout,setImmediate,MessageChannel,postMessage等
微任务: Promise.then(),MutationObserver
vm.$nextTick()原理: 优先使用Promise.resolve().then(flushCallback)
再次 MutationObserver
再次如果为Ie 使用setImmediate
最后采用setTimeout
2.webworker多线程
工作线程里不能使用ajax,不能操作dom 消息通信 onmessage (异步) postMessage,主要来处理数据计算(html跟js通信),不会堵塞主线程
let channel = new MessageChannel();
let port1 = channel.port1;
let port2 = channel.port2;
port1.postMessage('hello')
port2.onmessage = function(e) {
console.log(e.data)
}
serviceWorker 离线缓存
3.new Function
let func = new Function(arg1, arg2, ..., body); 历史原因,参数也可以以逗号分隔的列表的形式给出。
这三个意思相同:
new Function('a', 'b', 'return a + b'); // 基础语法
new Function('a,b', 'return a + b'); // 逗号分隔
new Function('a , b', 'return a + b'); // 逗号加空格分
4.一些常用正则
\s 匹配空白字符; \S 匹配非空白字符; +? 匹配 1 次或多次。
[\s\S]+? 就是匹配任意字符1次或多次。
. 匹配换行符以外的字符。
[.]+? 就是匹配换行符以外的字符1次或多次。
5.js中的错误
可分为语法错误和运行时错误
语法错误不会通过解析器,他会被标记为非法的JS并报告在控制台中。
alert(alarm);
这段代码是语法正确的,但是在C语言中,alarm是没有定义的,会被报告语法错误,所以静态语言的查错能力提前了,在程序编译的时候就会指出这种错误,但是JS没有这种能力,在解析器尝试运行这段代码的时候,会抛出“run-time error”。
捕获异常:
try {
alert(alarm);
}catch (error) {
alert("Uh oh...\n" + error);
}
finally {
console.log("finally一定会执行");
}
6.for await of
// 异步任务
function Gen(time) {
return new Promise((resolve, reject) => {
setTimeout(function () {
resolve(time)
}, time)
})
}
async function test() {
let arr = [Gen(2000), Gen(100), Gen(3000)]
for (let item of arr) {
console.log(Date.now(), await item.then(console.log))
}
}
test()
//1574145134469 Promise {<pending>}__proto__: Promise[[PromiseStatus]]: "resolved"[[PromiseValue]]: undefined
// 1574145134470 Promise {<pending>}
// 1574145134471 Promise {<pending>}
//100
//2000
//3000
在上述遍历的过程中可以看到三个任务是同步启动的,输出上也不是按任务的执行顺序输出的,这显然不太符合我们的要求。
for...of... 遍历同步操作,如果集合里有异步操作,for...of...无法拿到正确结果。
修改一下: 方案一
// 异步任务
function Gen(time) {
return new Promise((resolve, reject) => {
setTimeout(function () {
resolve(time)
}, time)
})
}
async function test() {
let arr = [Gen(2000), Gen(100), Gen(3000)]
for (let item of arr) {
let time = await item
console.log(Date.now(), time)
}
}
test()
// 1574145729887 2000
// 1574145729888 100
// 1574145730888 3000
三个任务在同步启动,但是是按照任务的执行顺序输出的 👍赞
方案二 es9的 for await of(只能在async里用)
// 异步任务
function Gen(time) {
return new Promise((resolve, reject) => {
setTimeout(function () {
resolve(time)
}, time)
})
}
async function test() {
let arr = [Gen(2000), Gen(100), Gen(3000)]
for await (let item of arr) {
console.log(Date.now(), item)
}
}
test()
// 1574145729887 2000
// 1574145729888 100
// 1574145730888 3000
结果也是ok的!for await of 只能在async函数里使用。
那么在自定义数据结构中,要遍历的对象有异步操作,应该怎么处理?
let obj = {
count: 0,
Gen (time) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve({ done: false, value: time })
}, time)
})
},
[Symbol.asyncIterator] () { // 挂载[Symbol.iterator] 属性
let self = this
return {
next () {
self.count++
if (self.count < 4) {
return self.Gen(Math.random() * 1000)
} else {
return Promise.resolve({
done: true,
value: ''
})
}
}
}
}
}
async function test () {
for await (let item of obj) {
console.log(Date.now(), item)
}
自定义数据结构不支持遍历,如果要使其支持遍历需要在对象上挂载 [Symbol.iterator] 属性,需遵循可迭代协议和迭代器协议。
7.async函数
一句话,async 函数就是 Generator 函数的语法糖。
形式上来讲:async 函数就是将 Generator 函数的星号(*)替换成 async,将 yield 替换成 await,仅此而已。
实际上:
(1)内置执行器。 Generator 函数的执行必须靠执行器,所以才有了 co 函数库,而 async 函数自带执行器。也就是说,async 函数的执行,与普通函数一模一样,只要一行。
var result = asyncReadFile();
(2)更好的语义。 async 和 await,比起星号和 yield,语义更清楚了。async 表示函数里有异步操作,await 表示紧跟在后面的表达式需要等待结果。
(3)更广的适用性。 co 函数库约定,yield 命令后面只能是 Thunk 函数或 Promise 对象,而 async 函数的 await 命令后面,可以跟 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)。
async函数的实现
async 函数的实现,就是将 Generator 函数和自动执行器,包装在一个函数里。
async function fn(args){
// ...
}
// 等同于
function fn(args){
return spawn(function*() {
// ...
});
}
多说无益,show me code:
function spawn(genF) {
return new Promise((resolve, reject) => {
let gen = genF()
function step(nextF) {
try {
var next = nextF()
} catch (error) {
return reject(error)
}
if (next.done) {
return resolve(next.value)
}
Promise.resolve(next.value).then(v => {
step(()=> gen.next(v))
}).catch(err => gen.throw(err))
}
step(() =>gen.next(undefined))
})
}
function* gen() {
yield 1
yield 2
return 3
}
spawn(gen).then(res => {
// console.log('suc',res)
}).catch(err => {
console.log('error',err)
})