网络请求》scriptText》Parser转义》AST》Ignition编译》ByteCode字节码》提取循环执行》优化编译器
- 执行js代码
- 解析源码并转成抽象语法树(AST)
- 基于AST,Ignition解释器产出字节码
- 同时运行代码并收集类型反馈
- 引擎检测到常用行为(循环)发生,以及使用的数据类型,为了更高效,字节码可以反馈数据一起被发送到优化编译器。优化编译器会经过假设实现高度优化的机器码【内联缓存技术(inline cashing)】
- 如果某些时候,其中一个假设不成立,优化编辑器就会取消优化,并回到解释器
AST
JavaScript解析器传成AST树:
^解析后的ast树
从上图中可以看出,我们只需要遍历这个树就能得知let关键字和其值。
执行上下文
一个变量提升可以看出来:
function () {
var x;
let n;
{
var l
let m
}
console.log(x,n,l)
console.log(m)
}
如果我们打印以上x,n,l,m
这时候会发现l,x,n都会打印,但m会报错。
它们可以用以下包含形式解释:
[var x=undefined; var l=undefiend]
[[let n[let m]]]
从上面可以看出关系是var定义的变量是在同一个区间内。而let定义的变量在同一个区间内的区域内。
var默认值为undefined,而let没有任何默认值。
javascript在执行时候,同步任务总是自上而下执行。
异步任务需要先判断是宏任务还是微任务。宏任务进宏任务队列,微任务进微任务队列。
宏任务
可以将每次执行栈执行的代码当做是一个宏任务
- I/O
- setTimeout
- setInterval
- setlmmediate
- requestAnimationFrame
微任务
当 宏任务 执行完,会在渲染前,将执行期间所产生的所有 微任务 都执行完
- process.nextTick (nodejs)
- MutationObserver
- Promise.then catch finally
先执行宏任务的第一个。在宏观上,因为我们把同步代码归为宏任务。同步任务就是第一个宏任务,但其实它没进宏任务队列。宏观上讲:宏任务》微任务。
好理解讲:同步任务(第一个宏任务)》微任务》宏任务
事件循环:
分析:
同步任务:log(1),log(7),直接执行。因此1,7先打印;
微任务:log(3),settimeout => log(4),log(5),因此能执行的只有3,5; settimeout => log(4)被压入宏任务栈。
宏任务:log(2),log(6),log(4)所以最后打印:2,6,4;
垃圾回收有几个常见的算法
引用计数,缺点也非常明显
标记清除
标记清除压缩
Cheney 算法,是目前用在 v8 新生代垃圾回收
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。