JavaScript底层知识

70 阅读3分钟

基础知识

JavaScript是解释型语言

浏览器嵌入了JavaScript引擎(如V8)用于解释JavaScript代码,解释后由CPU来执行,渲染至页面

JavaScript Engine

  • V8(Google): 由C++编写,开放源代码,由Google开发,是Google Chrome的一部分,也用于NodeJS
  • JavaScriptCore(Apple): 开放源代码,用于webkit型浏览器,如Safari,2008年实现了编译器和字节码解释器,升级为了SquirrelFish。苹果内部代号为"Nitro"的JavaScript引擎也是基于JavaScriptCore引擎的。
  • Rhino(Mozilla基金会): 由Mozilla基金会管理,开放源代码,完全以Java编写,用于HTMLUnit
  • SpiderMonkey(Mozilla): 第一款JavaScript引擎,早期用于Netscape Navigator,现时用于Mozilla Firefox。

V8的实现原理

image.png

  • 开始执行JavaScript代码
  • V8解析源代码并将其转化为抽象语法树(AST)
  • 基于该AST,Ignition解释器可以开始做它的事情,并产出字节码
  • 同时开始运行代码并收集类型反馈
  • 引擎可以检测到某些行为是否经常发生,以及使用的数据类型,为了使它运行得更快,字节码可以和反馈数据一起被发送到优化编译器。优化编译器在此基础上做出某些假设,然后产生高度优化的机器代码 [内联缓存技术(inline cashing)]
  • 如果在某些时候,其中一个假设被证明是不正确的,优化编译器就会取消优化,并回到解释器

Compiler

image.png

AST

代码转为AST:

let a = "aaaa"
{
  type: "Program",
  body: [
    {
      type: "VariableDeclarator",
      declarations: [{
        type: "VariableDeclarator",
        id: {
            type: "Identifier",
            name: "a"
         },
         init: {
           type: "Literal",
           value: "aaa",
           raw: "aaa"
         }
      }],
      kind: "let"
    }
  ],
  sourceType: "module"
}

执行上下文

函数或内容,代码在执行过程中需要分配存储空间,于是便有一个对象来表示当前的执行上下文

JavaScript始终在栈底存在一个全局上下文(Global Context)对象,当有其它上下文(函数)需要执行时,依次入栈,再依次出栈执行,执行至最后便仅剩全局上下文对象。

image.png

image.png

事件循环机制

JavaScript执行代码时,同步代码自上而下执行,异步代码分别进入微任务队列和宏任务队列等待执行。

在宏观上,把同步代码归为宏任务内容,但它不用进宏任务队列。

宏任务

JS每次从事件循环队列中取出一个宏任务执行,在执行过程中产生的宏任务将会放到事件循环队列中依次执行,每次执行栈执行的代码可以当作一个宏任务

  • I/O(NodeJS里的一些文件操作、流)
  • setTimeout
  • setInterval
  • setImmediate
  • requestAnimationFrame

微任务

当前执行栈里的同步代码执行完后,会在渲染前,将执行期间所产生的所有微任务都执行完

  • process.nextTick
  • MutationObserver
  • Promise.then/catch/finally

垃圾回收

image.png

垃圾回收常见的算法:

  • 引用计数
  • 标记清除
  • 标记清除压缩
  • Cheney算法,用在v8新生代垃圾回收