2020/8/13学习笔记整理

283 阅读4分钟

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)
})