当前位置: 首页 > 后端技术 > Node.js

JavaScript、Node.js与V8的关系

时间:2023-04-03 17:57:00 Node.js

对于了解Node的开发者来说,我们都知道Node是一个运行时环境(runtimeenvironment),可以让JavaScript运行在基于ChromeV8引擎开发的服务端。一方面,它提供了多种可调用的API,如读写文件、网络请求、系统信息等;另一方面,由于CPU执行的是机器码,它还负责将JavaScript代码解释成执行的一系列机器指令,这部分工作由V8引擎完成。MotivationJavaScript是一种具有自动垃圾收集功能的编程语言。市面上有这类功能的语言一般都有相应的虚拟机,比如Java的JVM,C#的CLR,PHP的Zend。虚拟机一般实现代码分析、内存管理、布局、垃圾回收等功能。不像C/C++这样的语言没有虚拟机,需要手动管理内存。C/C++语言编译的文件可以直接运行。我觉得学习一门开发语言,除了要知道一些语法用法和各种API调用。还需要学习相应的虚拟机。由于特殊的历史原因,JavaScript并不是V8的唯一引擎。但是目前V8是业界最好的JavaScript引擎,所以成为学习样本。今天的JavaScript不仅仅是在浏览器端使用,因为有了NodeJS,它也可以运行在服务器端。与浏览器端不同的是,服务器端对资源高度敏感。当业务规模变大,并发量变大的时候,一些非常小的问题就会被放大。这时候,一些小的内存泄漏就会造成灾难。所以作为JavaScript开发者,搞清楚从输入console.log('helloworld')到交给CPU执行的中间过程是非常重要的。这对于如何用JavaScript这种松散的语言写出高质量的代码也有一定的指导作用。要真正实现JavaScript全栈,任重而道远。NodeJS概述根据百度百科,Node.js是一个用于编写高性能Web服务器的JavaScript工具包。Node.js是一个可以快速构建网络服务和应用程序的平台。该平台基于Chrome的JavaScript运行时构建,也就是说,它实际上封装了GoogleV8引擎(适用于GoogleChrome浏览器)。V8引擎执行Javascript非常快,性能非常好。NodeJS不提供简单的封装,然后提供API调用,如果是这样的话,那也不会像现在这么流行。Node优化了一些特殊的用例,并提供了替代的API来让V8在非浏览器环境中运行得更好。例如,在服务器环境中,处理二进制数据通常是必不可少的,但Javascript缺乏对此的支持。因此,V8.Node增加了Buffer类来方便高效的处理二进制数据。因此,Node不仅简单地使用了V8,还对其进行了优化,使其在各种环境下更加强大。即时编译JIT概述V8使用即时编译技术(JIT)将JavaScript代码直接编译为本地平台的机器码。从宏观上看,步骤是JavaScript源代码->抽象语法树->本地机器码,后面的步骤只依赖于前面的步骤。这与其他口译员不同。比如Java语言需要先将源代码编译成字节码,然后再解释执行给JVM。JVM根据优化策略,在运行时有选择地将部分字节码编译成本地机器码。V8不生成中间码,一步编译成机器码,CPU开始执行。与生成中间代码并解释执行的方法相比,V8策略节省了一步,程序会更早开始运行。并且执行编译后的机器指令比解释和执行中间代码更快。缺点是缺少字节码的中间表示使得代码优化更加困难。V8概述作为一个JavaScript引擎,V8最初用于GoogleChrome浏览器。它随Chrome的第一个版本发布并开源。现在除了Chrome浏览器之外,它还有许多其他用户。如NodeJS、MongoDB、CouchDB等。JavaScript是一种基于原型的语言。基于其对Prototype继承的使用,V8采用了直译,即直接将JavaScript代码编译成机器码(MachineCode,有些地方也称为NativeCode),然后由硬件直接执行。与传统的“编译-解析-执行”过程不同,V8处理JavaScript时没有二进制代码或其他中间代码。简单来说,V8的主要工作就是:“将JavaScript翻译成机器码,然后运行”。但这往往是一个复杂的过程,需要处理很多问题,比如:编译、优化、内存管理、垃圾回收V8InNodeJS/NodeJS源码简述NodeJS,V8是如何引入的?我们关注Node的源码目录:.├──...├──deps│├──...│├──v8│├──...├──...├──lib│├──...│├──buffer.js│├──child_process.js│├──console.js│├──...├──node->out/Release/node├──。..├──out│├──...│├──发布|├──节点|├──node.d|├──对象|└──创|├──...|├──node_natives。h|├──...│├──...├──src│├──...│├──debug-agent.cc│├──debug-agent.h│├──env-inl。h│├──env.cc│├──...├──...需要注意的几个目录和文件:/deps/v8:这是V8源码所在的文件夹,你会发现目录结构与V8源码非常相似。NodeJS除了移植了V8源码之外,也在增加一些内容。/src:C/C++编写的核心模块所在文件夹。这部分用C/C++编写的模块称为“BuiltinModule”/lib:JavaScript编写的核心模块所在的文件夹。这部分称为“BuiltinModuleNativeCode”,在编译Node源码时,会使用V8自带的js2c.py工具,将所有内置的JavaScript代码转换为C++中的数组,并生成out/Release/obj/gen/node_natives.h文件,一些NativeModule需要借助BuiltinModules来实现其背后的功能。/out:该目录是Node源代码编译(命令行运行make)后生成的目录,其中包含Node的可执行文件。当你在命令行输入nodexxx.js的时候,实际上运行的是out/Release/node文件,下面用一张图来说明V8在Node中运行的整体过程,Node在启动的时候已经加载了NativeModule和BuiltinModule进入内存,后面的JavaScript代码需要V8动态编译解析运行。