简述 JavaScript 被执行的那些事情

简述 JavaScript 被执行的那些事情

JavaScript 是脚本语言

JavaScript 是解释型语言

JavaScript 执行流程

不同浏览器有不同的 JavaScript 引擎(运行时),主流的 JS 引擎有:

  • V8,chromium 内核的引擎,主要用于 chrome 和 node,目前来说是最主流,大概也是性能最高的 JS 引擎
  • SpyderMonkey,火狐的 JS 殷勤
  • JavaScriptCore,webkit 的引擎,它的名字好多,还包含 SquirrelFish、Nitro,不过项目名称是 JavaScriptCore

抛开早期的 JS 引擎不谈,现在的 JS 引擎的确是会先对 JS 进行编译——即时编译(just-in-time compiling)——,将其转化成二进制的机器语言并处理数据,从而提升运行速度。不过本质上 JS 还是一种解释型语言,因为代码还是一边运行一边执行的。

下面这张图是 v8 的执行过程:

在这里插入图片描述

其中 bytecode 就是二进制的机器码,是由 JIT 编译而成,具体执行的过程是在 baseline 这里(针对 v8,其他的引擎的名称不一样,大致执行流程是差不多的)。

内存管理

JavaScript 的内存管理和其他主流的编程语言差不多,主要就是存储没这么昂贵的(primitive data type)和函数会被存放在 stack 中,存储起来比较昂贵的会被存放到 heap 中:

在这里插入图片描述

以下面代码为例:

function c() {
    
    
  console.log('c');
}

function b() {
    
    
  c();
  console.log('b');
}

function a() {
    
    
  b();
  console.log('a');
}

a();

这时候的 stack 中的保存值为:

在这里插入图片描述

当 c 执行完毕后,c 执行完毕后,就会被退栈,然后执行 b,以此类推。搭配上引擎的事件池,这也是为什么目前 JS 对于异步的操作非常高效的缘故:

event loop

递归也是这样的操作,每次调用之后就会将当前函数再一次推到栈中,一直到 base case。这也是为什么一旦 base case 没有定义好,就会出现 stack excced limits 的报错。

垃圾回收

JavaScript 高级程序设计第四章学习笔记 有提,常规的有两种:

  • 标记清理(mark-and-sweep) :最常用的垃圾回收策略。

    其基本策略就是根据 执行上下文 去判断当前变量是否还在使用中,并且进行标记。一旦离开了 当前执行上下文 的范围内,该函数就会被标记为 离开当前执行上下文。在 垃圾回收 机制运行时,它会检查所有的标记,确认无用的变量后,再加上 待删除 的标记,最后执行内存清理,清理掉 待删除 的标记,释放空间。

  • 引用计数

    引用计数(reference computing) 是另外一种没那么常用的垃圾回收机制。其基本思路是标记每一个变量被引用的次数,当这个函数被调用时,引用的次数 +1,当保存该值引用的值被其他的覆盖了,引用的次数 -1。最终当引用的次数为 0 的时候,就被认定可以安全地释放其内存,并且会在下次垃圾回收机制运行的时候释放其空间。

    在互相引用的情况下,这个回收机制就会出现问题——引用计数永远不会为 0,这也代表着互相调用的内存永远不会被清空。

    其中一个人为的补救方式是将指针对象指向 null,即:

    const someSbject = {
          
          };
    // ........
    someSbject = null; // 完全切断变量与引用之间的关系
    

reference

其他一些相关的学习红宝书第四章也有,这里是笔记:

猜你喜欢

转载自blog.csdn.net/weixin_42938619/article/details/130715570