说明:
V8是node很重要的一个模块,是执行js代码的引擎。我们主要通过使用V8的API来完成C++ 和 Node之间的变量类型转换、异步调用的实现和类的封装等。
主要知识点:
1.Nodejs主要由V8和libuv组成;
2.V8是js运行的引擎;
3.Nodejs变量的创建和内存的释放都是通过V8;
4.V8可以是C++ Addon访问和转换js变量;
5.存储单元在JS和C++中都没有引用的情况下才会被回收;
6.可以把Local 看成 智能指针。
Isolates
1.每一个isolate都有一个独立的堆,保存创建的变量和运行环境;
2.Nodejs只有一个isolate,而且不能再创建;(源码中加锁限制其他线程创建)
3.不能再其他线程中调用isolate;
4.可以把多个V8嵌入C++程序中,是程序可以创建多个isolate,但是要有时候保持isolate的同步是个棘手的问题。
Contexts
1.包含了执行环境和堆:全局变量、变量、函数、系统函数、对象、模块、句柄、文档等等;
2.每个上下文都是独立的,包含自己的运行环境和堆;
3.我们只能通过V8获取、创建、修改上下文的内容。
JavaScript variables, C++ Handles
HandleScope
1.异步函数和回调参数只能通过HandleScope获取相应的参数;
2.HandleScope不能创建;
3.Local handle 在回调或者C++返回到js的时候进行垃圾回收;
4.在很多例子中都能看到,直接使用了HandleScope,那是因为Nodejs在调用我们写的Addon之前创建了一个HandleScope 对象。
V8 Data Type
基本类型
Strings Numbers Booleans null undefined
通过V8 API操作基础数据,而不是直接操作又三个原因:
js基本类型的存储机制不可变:js中var x = 5,分配了一个存储单元 a;当 x = 6,a存储单元的值没有改变,而是新建立了一个值为6的存储单元b,x指向b。
js调用C++时,通过参数(传值的方式),内部空间对参数的操作不会影响外部变量。
Handles能记录变量的引用数,在引用数为零的时候,可以通过垃圾回收机制清空无效引用。
Number -> double
void PassNumber(const FunctionCallbackInfo<Value>& args) {
Isolate * isolate = args.GetIsolate();
// 方式1
Local<Number> target = args[0]->ToNumber();
// 方式2
double value = target->NumberValue();
// value is now OUTSIDE of V8 - we can use it in
// all the C++ standard ways.
}
新建Number并返回
void PassNumber(const FunctionCallbackInfo<Value>& args) {
Isolate * isolate = args.GetIsolate();
// 如果 参数为空,则返回NAN ; NAN+=42 还是等于NAN
double value = args[0]->NumberValue();
value+= 42;
// 新建,必须获取V8内核的独立堆
// 在V8内核的堆上床架一个存储单元,并把value赋值给存储单元
// retval指向这个存储单元
Local<Number> retval = Number::New(isolate, value);
// 返回
args.GetReturnValue().Set(retval);
}
JS调用
const addon = require('./build/Release/primitive');
var number_returned = addon.pass_number(23);
console.log(number_returned); // prints 65
var number_returned = addon.pass_number(0.5);
console.log(number_returned); // prints 42.5
Number -> int
void PassInteger(const FunctionCallbackInfo<Value>& args) {
Isolate * isolate = args.GetIsolate();
// 如果传进来的是是5.7 则v8会自动取整为5
int value = args[0]->Int32Value();
Local<Number> retval = Int32::New(isolate, value + 42);
args.GetReturnValue().Set(retval);
}
Boolean -> bool
void PassBoolean(const FunctionCallbackInfo<Value>& args) {
Isolate * isolate = args.GetIsolate();
// Null、未定义、0和空字符串总是被转换为false。
// 其他一切(包括空对象和数组)都被认为是正确的。