网站首页 > 技术文章 正文
Node.js 的高性能源于其底层实现,这些模块主要由 C++ 编写。因此,理解 Node.js 底层组成及掌握 C++ 核心概念是深入学习的关键。
JavaScript 1. Node.js 底层组成
Node.js 是基于 Chrome V8 引擎的 JavaScript 运行时,其高效的事件驱动和非阻塞 I/O 能力由以下核心组件实现:
1.1 V8 引擎
- 功能 :解析和执行 JS 代码,通过 JIT 编译转为机器码。
- 实现 :C++ 编写,管理 JS 对象、内存分配(垃圾回收)和执行上下文(如 Isolate 、 Context )。
- 作用 :执行 JS 代码,如事件回调、Promise。 #技术分享
1.2 libuv 库
- 功能 :跨平台异步 I/O,负责事件循环、线程池和非阻塞 I/O(文件、网络)。
- 实现 :主要 C,部分 C++,提供事件循环、句柄和流。
- 作用 :实现事件驱动,处理异步任务(如 setTimeout 、文件操作)。
C 1.3 C++ 绑定层
- 功能 :桥接 V8 和 libuv,核心模块(如 fs 、 http )通过 C++ 实现。
- 实现 :使用 C++ 和 N-API。
- 作用 :提供 JS 与底层的接口,如 Buffer 内存管理。
1.4 其他组件
- c-ares :异步 DNS 解析。
- OpenSSL :HTTPS 和加密。
- zlib :压缩(如 gzip)。
- http-parser :HTTP 请求/响应解析。
C 2. C++ 基础与核心概念
Node.js 底层依赖 C++,以下结合 Node.js 场景讲解 C++ 基础和核心概念。
C 2.1 C++ 基础语法
C++ 是高效的系统级语言,支持过程式、面向对象和泛型编程,注重手动内存管理和性能。
2.1.1 基本结构
#include <iostream>
int main() { std::cout << "Hello, Node.js from C++!" << std::endl; return 0; }
- 头文件 : #include 引入库, std:: 是标准命名空间。
- main 函数 :程序入口。
- 编译 : g++ hello.cpp -o hello && ./hello .
2.1.2 数据类型
C++ 是强类型语言:
- 整数: int 、 long .
- 浮点: float 、 double .
- 字符: char .
- 布尔: bool .
int age = 25
double pi = 3.14159
char grade = 'A'
bool isNodeDeveloper = true
const int MAX_AGE = 100 enum Color { RED, GREEN, BLUE } Color myColor = RED
V8 用 double 表示 JS Number。
2.1.3 控制结构
- 条件: if-else 、 switch .
- 循环: for 、 while .
int main() {
int n = 10
long long fib[10]
fib[0] = 0
fib[1] = 1
for (int i = 2
fib[i] = fib[i-1] + fib[i-2]
}
for (int i = 0
std::cout << fib[i] << " "
}
std::cout << std::endl
return 0
}
2.1.4 函数
int add(int a, int b) {
return a +
}
int main() { std::cout << add(5, 3) << std::endl; return 0; }
Node.js 扩展用 C++ 函数定义导出方法。
2.1.5 类和面向对象编程
C++ 的面向对象编程(OOP)是其核心特性,支持封装、继承、多态和抽象,广泛用于 Node.js 底层(如 V8 的 Isolate 和 Context )。
2.1.5.1 封装
封装通过类将数据和方法绑定,访问控制( public 、private 、protected )保护数据。
#include <string>
# include <iostream>
class Person { private: std::string name; int age; public: Person(std::string n, int a) : name(n), age(a) {} void setName(std::string n) { name = n; } std::string getName() const { return name; } void greet() const { std::cout << "Hello, I'm " << name << ", age " << age << std::endl; } };
int main() { Person p("NodeDev", 30); p.greet(); p.setName("JSDev"); std::cout << p.getName() << std::endl; return 0; }
- 应用 :V8 的类(如 v8::Object )用封装管理 JS 对象属性。
2.1.5.2 继承
继承允许子类复用父类代码,支持代码重用和层次结构。
#include <string>
# include <iostream>
class Person { protected: std::string name; public: Person(std::string n) : name(n) {} virtual void greet() const { std::cout << "I'm " << name << std::endl; } };
class Developer : public Person { private: std::string language; public: Developer(std::string n, std::string lang) : Person(n), language(lang) {} void greet() const override { std::cout << "I'm " << name << ", a " << language << " developer" << std::endl; } };
int main() { Developer dev("NodeDev", "JavaScript"); dev.greet(); return 0; }
- virtual 和 override :支持多态,子类可重写父类虚函数。
- 应用 :V8 的对象层次结构(如 v8::Value 的子类 v8::Object 、 v8::Function )。
2.1.5.3 多态
多态通过虚函数和指针/引用实现运行时行为动态选择。
#include <iostream>
class Shape { public: virtual double area() const = 0; virtual ~Shape() = default; };
class Circle : public Shape { private: double radius; public: Circle(double r) : radius(r) {} double area() const override { return 3.14159 *
};
int main() { Shape* shape = new Circle(5.0); std::cout << "Area: " << shape->area() << std::endl; delete shape; return 0; }
- 应用 :V8 的多态类(如 v8::Value )处理不同 JS 类型。
2.1.5.4 抽象和接口
纯虚函数定义接口,强制子类实现。
#include <iostream>
class Printable { public: virtual void print() const = 0; virtual ~Printable() = default; };
class Document : public Printable { public: void print() const override { std::cout << "Printing document" << std::endl; } };
int main() { Printable* doc = new Document(); doc->print(); delete doc; return 0; }
- 应用 :libuv 的句柄(如 uv_handle_t )通过抽象类定义通用接口。
2.1.5.5 OOP 在 Node.js 底层
- V8 : Isolate 和 Context 使用类封装运行时状态,继承和多态管理对象层次。
- libuv :句柄和流通过抽象类实现跨平台接口。
- N-API :类封装 JS 对象操作,简化扩展开发。
2.2 核心概念一:指针
2.2.1 指针基础
#include <iostream>
int main() { int x = 10; int* ptr = &x; std::cout << "x: " << x << std::endl; std::cout << "ptr: " << ptr << std::endl; std::cout << "*ptr: " << *ptr << std::endl; return 0; }
2.2.2 指针运算和数组
int arr[3] = {1, 2, 3};
int*
for (int i = 0; i < 3; ++i) { std::cout << *(p +
} std::cout << std::endl;
Node.js 的 Buffer 是 char* 指针数组。
2.2.3 动态内存
int* dynamicPtr = new int
*dynamicPtr = 42
std::cout << *dynamicPtr << std::endl
delete dynamicPtr
dynamicPtr = nullptr
2.2.4 智能指针
#include <memory>
# include <iostream>
struct Node { int data; Node(int d) : data(d) { std::cout << "Node created\n"; } ~Node() { std::cout << "Node destroyed\n"; } };
int main() { std::shared_ptr<Node> ptr1 = std::make_shared<Node>(42); std::cout << ptr1->data << std::endl; return 0; }
V8 的 v8::Persistent 使用类似机制。
2.2.5 指针陷阱
- 空指针:访问 nullptr 崩溃。
- 野指针:释放后未置空。
- 越界:访问数组边界外。
2.3 核心概念二:引用
#include <iostream>
int main() { int x = 10; int& ref = x; ref = 20; std::cout << "x: " << x << std::endl; return 0; }
- 应用 :V8 的 v8::Local 传递对象,N-API 用引用管理回调。
2.4 核心概念三:内存管理
2.4.1 栈与堆
int* createArray(int size) {
int* arr = new int[size];
for (int i = 0; i < size; ++i) {
arr[i] = i;
}
return arr;
}
int main() { int* arr = createArray(5); for (int i = 0; i < 5; ++i) { std::cout << arr[i] << " "; } std::cout << std::endl; delete[] arr; return 0; }
2.4.2 RAII
资源获取即初始化,libuv 的句柄基于此。
2.5 核心概念四:模板
2.5.1 模板函数
#include <iostream>
template <typename T>
T max(T a, T b) { return a > b ? a : b; }
int main() { std::cout << max(5, 3) << std::endl; std::cout << max(3.14, 2.71) << std::endl; return 0; }
2.5.2 模板类
#include <iostream>
# include <string>
template <typename T>
class Box { T value; public: Box(T v) : value(v) {} T getValue() const { return value; } };
int main() { Box<int> intBox(42); Box<std::string> strBox("Node.js"); std::cout << intBox.getValue() << std::endl; std::cout << strBox.getValue() << std::endl; return 0; }
- 应用 :V8 的 v8::Local<T> ,libuv 平台抽象。
2.6 核心概念五:多线程
2.6.1 线程
#include <iostream>
# include <thread>
void worker() { std::cout << "Worker thread\n"; }
int main() { std::thread t(worker); t.join(); std::cout << "Main thread\n"; return 0; }
2.6.2 互斥锁
#include <iostream>
# include <thread>
# include <mutex>
std::mutex mtx; int counter = 0;
void increment() { for (int i = 0; i < 1000; ++i) { std::lock_guard<std::mutex> lock(mtx); ++counter; } }
int main() { std::thread t1(increment); std::thread t2(increment); t1.join(); t2.join(); std::cout << "Counter: " << counter << std::endl; return 0; }
- 应用 :libuv 线程池,Node.js Worker Threads。
2.7 核心概念六:异常处理
#include <iostream>
# include <stdexcept>
double divide(double a, double b) { if (b == 0) { throw std::runtime_error("Division by zero!"); } return a / b; }
int main() { try { std::cout << divide(10, 0) << std::endl; } catch (const std::runtime_error& e) { std::cout << "Error: " << e.what() << std::endl; } return 0; }
- 应用 :V8 的 v8::TryCatch ,N-API 错误传递。
2.8 核心概念七:STL
2.8.1 容器
#include <iostream>
# include <vector>
# include <map>
# include <string>
int main() { std::vector<int> vec = {1, 2, 3}; vec.push_back(4); for (int x : vec) { std::cout << x << " "; } std::cout << std::endl;
std::map<std::string, int> scores; scores["Alice"] = 90; scores["Bob"] = 85; for (const auto& pair : scores) { std::cout << pair.first << ": " << pair.second << std::endl; } return 0; }
2.8.2 算法
#include <iostream>
# include <vector>
# include <algorithm>
int main() { std::vector<int> vec = {4, 2, 5, 1, 3}; std::sort(vec.begin(), vec.end()); for (int x : vec) { std::cout << x << " "; } auto it = std::find(vec.begin(), vec.end(), 3); if (it != vec.end()) { std::cout << "\nFound: " << *it << std::endl; } return 0; }
- 应用 :V8 用 std::vector 存储属性,libuv 用容器管理回调。
C 3. C++ 包管理器与 V8/libuv 安装
C 3.1 C++ 包管理器
3.1.1 vcpkg
- 功能 :微软跨平台 C++ 库管理器。
- 安装 :
git clone https://github.com/microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
.\bootstrap-vcpkg.bat
./vcpkg integrate install
3.1.2 Conan
- 功能 :跨平台 C++ 包管理器,支持二进制分发。
- 安装 : pip install conan .
3.1.3 系统包管理器
- Linux: apt , yum , pacman .
- macOS: brew install <package> .
- Windows:推荐 vcpkg/Conan。
3.2 安装 V8
3.2.1 vcpkg
vcpkg install v8
- CMake 集成: find_package(V8) .
3.2.2 手动编译
git clone https://chromium.googlesource.com/v8/v8.git
cd v8
git checkout <version>
tools/dev/v8gen.py x64.release ninja -C out.gn/x64.release
3.3 安装 libuv
3.3.1 vcpkg
vcpkg install libuv
3.3.2 系统包管理器
- Ubuntu: sudo apt install libuv1-dev
- macOS: brew install libuv
3.3.3 手动编译
git clone https://github.com/libuv/libuv.git
cd libuv
mkdir build && cd build
cmake .. -DBUILD_TESTING=OFF
make && make install
3.4 编译示例程序
V8 示例
执行 JS 代码:
#include <v8.h>
# include <libplatform/libplatform.h>
# include <iostream>
int main() { v8::V8::InitializeICU(); auto platform = v8::platform::NewDefaultPlatform(); v8::V8::InitializePlatform(platform.get()); v8::V8::Initialize();
v8::Isolate::CreateParams create_params; create_params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator(); v8::Isolate* isolate = v8::Isolate::New(create_params);
{ v8::Isolate::Scope isolate_scope(isolate); v8::HandleScope handle_scope(isolate); v8::Local<v8::Context> context = v8::Context::New(isolate); v8::Context::Scope context_scope(context);
v8::Local<v8::String> source = v8::String::NewFromUtf8(isolate, "'Hello, V8!'").ToLocalChecked(); v8::Local<v8::Script> script = v8::Script::Compile(context, source).ToLocalChecked(); v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();
v8::String::Utf8Value utf8(isolate, result); std::cout << *utf8 << std::endl; }
isolate->Dispose(); v8::V8::Dispose(); v8::V8::DisposePlatform(); delete create_params.array_buffer_allocator; return 0; }
- 编译 : g++ -I$vcpkg/installed/x64-linux/include -L$vcpkg/installed/x64-linux/lib v8_example.cpp -lv8_monolith -o v8_example .
libuv 示例(定时器)
#include <uv.h>
# include <iostream>
void timer_cb(uv_timer_t* handle) { std::cout << "Timer fired!" << std::endl; uv_stop(handle->loop); }
int main() { uv_loop_t* loop = uv_default_loop(); uv_timer_t timer; uv_timer_init(loop, &timer); uv_timer_start(&timer, timer_cb, 1000, 0); uv_run(loop, UV_RUN_DEFAULT); uv_loop_close(loop); return 0; }
- 编译 : g++ -I$vcpkg/installed/x64-linux/include -L$vcpkg/installed/x64-linux/lib libuv_timer.cpp -luv -o libuv_timer .
libuv 示例:简单的异步 Web 服务器
以下是一个使用 libuv 实现简单异步 HTTP 服务器的示例。它基于事件循环监听 TCP 连接,接收请求后返回固定 HTTP 响应("Hello World!"),展示 libuv 的异步非阻塞 I/O 能力。
#include <stdio.h>
# include <stdlib.h>
# include <uv.h>
# define DEFAULT_PORT 7000
#define DEFAULT_BACKLOG 128
uv_loop_t *loop;
void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) { buf->base = (char*) malloc(suggested_size); buf->len = suggested_size; }
void on_close(uv_handle_t *handle) { free(handle); }
void echo_read(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) { if (nread < 0) { if (nread != UV_EOF) { fprintf(stderr, "Read error %s\n", uv_err_name(nread)); } uv_close((uv_handle_t*) client, on_close); free(buf->base); return; }
const char *response = "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello World!"; uv_write_t *req = (uv_write_t *) malloc(sizeof(uv_write_t)); uv_buf_t wrbuf = uv_buf_init((char*)response, strlen(response)); uv_write(req, client, &wrbuf, 1, NULL);
uv_close((uv_handle_t*) client, on_close); free(buf->base); }
void on_new_connection(uv_stream_t *server, int status) { if (status < 0) { fprintf(stderr, "New connection error %s\n", uv_strerror(status)); return; }
uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t)); uv_tcp_init(loop, client); if (uv_accept(server, (uv_stream_t*) client) == 0) { uv_read_start((uv_stream_t*) client, alloc_buffer, echo_read); } else { uv_close((uv_handle_t*) client, on_close); } }
int main() { loop = uv_default_loop();
uv_tcp_t server; uv_tcp_init(loop, &server);
struct sockaddr_in addr; uv_ip4_addr("0.0.0.0", DEFAULT_PORT, &addr);
uv_tcp_bind(&server, (const struct sockaddr*)&addr, 0); int r = uv_listen((uv_stream_t*) &server, DEFAULT_BACKLOG, on_new_connection); if (r) { fprintf(stderr, "Listen error %s\n", uv_strerror(r)); return 1; }
printf("Server listening on port %d\n", DEFAULT_PORT); return uv_run(loop, UV_RUN_DEFAULT); }
- 说明 :服务器监听 7000 端口,接受连接后读取数据,并返回简单 HTTP 响应。使用 libuv 的事件循环实现异步处理,支持并发连接而非阻塞。
- 编译 : g++ -I$vcpkg/installed/x64-linux/include -L$vcpkg/installed/x64-linux/lib libuv_http_server.cpp -luv -o libuv_http_server .
- 运行 : ./libuv_http_server ,然后用浏览器访问 http://localhost:7000 测试。
总结
本文介绍了 Node.js 的底层组成(V8、libuv 等)、C++ 核心概念(新增面向对象编程能力)、C++ 包管理器及 V8/libuv 安装方法,并使用 libuv 实现简单异步 Web 服务器的示例。
猜你喜欢
- 2025-10-14 25元、264KB内存的微处理器,树莓派出品,带快速休眠模式
- 2025-10-14 系列专栏(十一):类语法_语法词类
- 2025-10-14 C++ 23的std::print,终于可以和printf说再见了
- 2025-10-14 常指针、函数指针、结构体内部指针、通用指针原理解读
- 2025-10-14 大模型为什么非要在GPU上运行?_为什么做模型
- 2025-10-14 C++/C入门之拷贝构造函数--C++之美
- 2025-10-14 C/C++语言const常量与#define宏常量的比较
- 2025-10-14 C++作死代码黑榜:避坑实战手册_c++代码怎么写
- 2025-10-14 C++ ADL(实参依赖查找/Koenig查找)如何打破可见性规则?
- 2025-10-14 重温C++编程-语法篇-让我们回到C++的世界
- 最近发表
- 标签列表
-
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (95)
- pythoncase语句 (88)
- es6includes (74)
- sqlset (76)
- apt-getinstall-y (100)
- node_modules怎么生成 (87)
- chromepost (71)
- flexdirection (73)
- c++int转char (80)
- mysqlany_value (79)
- static函数和普通函数 (84)
- el-date-picker开始日期早于结束日期 (76)
- js判断是否是json字符串 (75)
- c语言min函数头文件 (77)
- asynccallback (87)
- localstorage.removeitem (77)
- vector线程安全吗 (70)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- 无效的列索引 (74)