把v8当做新的框架,新的语言来学习,从上JS,从下C++;在V8里有着自己一套的API和规则。 version:6.*

基本概念

内存机制

javascript中使用的数据类型,声明的变量,由chrome v8管理内存机制管理;
node重要的两部分:

  • chrome V8 提供 js运行环境,解释执行js
  • libuv 提供跨平台的事件循环机制,以及各种基础库

c++扩展 在Chrome V8中的实例中创建的变量,能够被js访问到,js创建,声明的数据,也能在一定的条件下被C++扩展访问;

Chrome V8 中创建的数据存储单元,不能被显示的回收,只能等待内存回收机制判断;
chrome V8 - 图1

新生代

分配的对象小,垃圾回收频繁;
新生代内存采用Scavenge算法进行垃圾回收;
chrome V8 - 图2
当分配新的数据,指向内存区指针到了新生代内存末尾,触发一次清理(没地方可用了);
当经历到第二次清理时,会晋升至老生代(查过一次还不死的数据);
当垃圾回收时To空间已经被占据25%,会晋升至老生代

老生代

老生代数据量大,采用Scavenge,耗时大,其使用Mark-sweep(标记清除)+Mark-Compact(标记整理)

  • Mark-sweep 标记清理,标记阶段,标记活着的数据;清理阶段,清理未被标记的数据。
  • Mark-Compact 标记整理,当老生代空间不足以存放晋升过来的新生代数据时,使用此方法;因为标记清理会造成内存碎片(内存空间不连续),解决办法就是在标记清理的清除阶段,让活着的对象整齐排放,留出空间;

隔离实例(Isolate)

v8引擎实例!!单个实例内部有着独立的堆管理,垃圾回收;如果自定义node。为其添加多个隔离实例,那么实例之间互不干扰。

上下文(Context)

上下文对象,定义JS执行环境的对象

脚本(Script)

包含已经编译好的JS脚本对象

常用数据类型

js层面的数据到了v8层面,这些数据都基于V8:value 这个基类而来,当不确定数据的类型是,使用v8:value可以解决不方便之处。
Value主要有两种方法Is判断数据类型,To转化数据类型(实际是得到另一种类型的的句柄)
image.pngimage.png

句柄

什么时候,对象数据才是不被引用的对象,即死亡对象数据?
当一个对象不再被句柄引用之后,他就是垃圾;句柄不同于指针,垃圾回收的时候,内存数据会被移动,如果使用指针,最后指向的数据就会不对,使用句柄,数据的引用关系保存在垃圾回收器;

句柄作用域

句柄活动的范围,一般在函数体开始声明。一个句柄作用域管理其域中的句柄,感觉句柄作用域是湖泊,句柄是鱼!

chrome V8 - 图5

本地句柄

句柄是v8中定义的一种数据对象,有着自己定义,声明,属性方法,

本地句柄存储在栈内存

静态成员函数(6.17.1)

image.png

成员函数

image.png

  • NEW(创建)
  • Clear(清除)
  • IsEmpty(判断空句柄)
  • AS/Cast(不同数据类型的本地句柄转换)

持久句柄

其提供堆内存中一个JS对象的引用
当JS对象引用只有一个(弱)持久句柄时,v8垃圾回收会触发一个回调;

永生句柄(Eternal)

永生了

待实本地句柄(Maybe Local)

特别的本地句柄,当不确定获取的本地句柄是否为空,用此句柄类型提醒自己

句柄作用域

可以把句柄作用域看做小说里面的一方世界,句柄是这方世界的生灵。作用域结束的时候,这方“世界”的生灵基本都会被抹去,除去个别几种。

一般句柄作用域

可逃句柄作用域

模板(Template)

函数模板(Function Template)

按照官网的介绍,函数模板用于运行时创建函数,且在一个上下文通过函数模板有且创建一个函数,被创建的函数生命周期与上下文的生命周期一致。
通过下面的代码,我们可以通过函数模板到将C++等扩展函数,为JS所用;

  1. void Method(const <Value> &args){
  2. Isolate* isolate = args.GetIsolate();
  3. args.GetReturnValue().Set(String::NewFromUtf8(isolate,"this is a function"));
  4. }
  5. void init(Local<Object> exports)
  6. {
  7. Isolate* isolate =Isolate::GetCurrent();
  8. HandleScope scope(isolate);
  9. Local<FunctionTemplate> funtem = FunctionTemplate::New(isolate,Method);
  10. Local<Function> fn = funtem -> GetFunction();
  11. Local<String> name = String::NewFromUtf8(isolate,"functionName");
  12. fn->SetName(name);
  13. exports->Set(name,fn);
  14. }

对象模板(Object Template)

官方介绍很少,运行时创建对象;添加到Object Template 的属性,其创建的对象也会拥有这个属性(类似原型链);

访问器(accessor)

在访问(get)或操作(set)对象特定属性时可以做某些事情;
对象模板通过SetAccessor()设置访问器;

拦截器(Interceptor)

对于一个对象实例所有操作进行拦截操作;

同样是对象模板上的操作,通过SetHandler()来实现;
从api上来看有两种实现方式:

  1. SetHandler (const NamedPropertyHandlerConfiguration &configuration)
  2. SetHandler (const IndexedPropertyHandlerConfiguration &configuration)

前者通过属性名字限制,后者通过属性下标

内置对象

内置字段,js层面不可见,只能在c++层面可见且操作;
内置对象除了是v8中定义的对象数据之外
还可以操作C++ 中自定义的struct/数据类型.这些数据类型和结构是v8没有的。

常用数据类型

image.png
V8文档
v8::Value 可以说是其他数据类型的基类了。
在关于v8::Value的文档中,我们可以看出关于Value的API大致有以下几种:
IS
image.png
TO
image.png

下面是一些常见的数据类型API 以及用例

string

创建一个v8:String

  1. // 将char* 转化成string
  2. MaybeLocal<String> mbtestString = String::NewFromUtf8(isolate,"if like is time",NewStringType::kNormal);
  3. Local<String> testString = mbtestString.ToLocalChecked();

将v8:String转成char

  1. String::Utf8Value charStr(testString);
  2. if(charStr.length() !=0){ // 上述转换可能会失败,length=0
  3. char* ret = *charStr;
  4. printf("%s\n",ret);
  5. }

数值类型

NumberIntergerInt32Uint32
使用起来基本都是New()或者Value()

Boolean

和其他类似

Object

不考虑Obj 作为function或者其他拦截器,访问器等功能的化,仅仅类似JS Object 去考虑功能,初始化,set,get,del 等对象操作

  1. Local<Object> obj = Object::New(isolate); // 用obj 设置值,获取值,删除值
  2. Local<String> key = String::NewFromUtf8(isolate,"objkey",NewStringType::kNormal).ToLocalChecked();
  3. Local<Number> value = Number::New(isolate,1234);
  4. obj->Set(context,key,value).FromJust();// 校验结果通过 FromJust来触发异常使程序崩溃
  5. Local<Value> getValue = obj->Get(context,key).ToLocalChecked();
  6. Local<Number> getValueNum = getValue->ToNumber(context).ToLocalChecked();
  7. printf("obj get value is %f\n",getValueNum->Value());
  8. obj->Delete(context,key).FromJust();
  9. Local<Value> getValueDel = obj->Get(context,key).ToLocalChecked(); // 这里取值已经取不到值了
  10. Local<Number> getValueNumDel = getValueDel->ToNumber(context).ToLocalChecked();
  11. printf("obj get value is %f\n",getValueNumDel->Value());

Array

和js中的数组操作类似

New 一个

  1. Local<Array> arr = Array::New(isolate,10);//长度为10的数组

set&&get

数组继承Object.所以有着Object的方法;

  1. // Get
  2. MaybeLocal< Value > Get (Local< Context > context, uint32_t index)
  3. // Set
  4. Maybe< bool > Set (Local< Context > context, uint32_t index, Local< Value > value)

简单使用

尝试存取arr中的一个string

  1. Local<Array> arr = Array::New(isolate,10);
  2. char ret[512];
  3. strcpy(ret,"下标为0的值");
  4. printf("数组设置的值是:%s\n", ret);
  5. //存
  6. arr->Set(context,0,String::NewFromUtf8(isolate,ret,NewStringType::kNormal).ToLocalChecked());
  7. // 取
  8. Local<Value> arrvalue = arr->Get(context,0).ToLocalChecked();
  9. if(arrvalue->IsString()){
  10. printf("判断一下是不是string");
  11. }
  12. String::Utf8Value arrvaluechar(arrvalue);
  13. if(arrvaluechar.length() !=0){
  14. char* retarr = *arrvaluechar;
  15. printf("Arr index 0 get value: %s\n", retarr);
  16. }

Function

函数来源,从外部而来的value类型是函数,那么可以通过Cast将其转化成Function;还有就是C++层面通过函数模板创建的Function;
利用Call调用外部的方法;
下面用1+1等方式接入chrome V8 层面对函数类型的操作

  1. void Add(const FunctionCallbackInfo<Value>& args)
  2. {
  3. Isolate* isolate = args.GetIsolate();
  4. Local<Context> context = isolate->GetCurrentContext();
  5. Local<Number> num1 = args[0].As<Number>();
  6. Local<Number> num2 = args[1].As<Number>();
  7. Local<Function> func =args[2].As<Function>();// 回调函数
  8. Local<Value> null = v8::Null(isolate); // 回调函数this
  9. double addret = num1->Value() + num2->Value();
  10. Local<Number> value = Number::New(isolate, addret);
  11. Local<Value> reArgv[1] = {value};
  12. func->Call(context, null, 1, reArgv);
  13. args.GetReturnValue().Set(value);
  14. }

编译之后使用

  1. const test =require("../build/Release/addon.node");
  2. test(1,1,(ret)=>{
  3. console.log(ret); //2
  4. })

其中FunctionCallbackInfo为方法的参数,参数通过数组下标获取;ReturnValue是函数返回值的载体,可以设置返回值;

JSON(parse)

关于json 数据解析
image.png

异常

关于异常 类似JS 主要有捕获,抛出,异常处理;

TryCatch

trycatch 也是一种数据类型,用来对v8层面的异常捕获;

其他

Maybe

v8有许多返回maybe 类型的api;比如V8:Object的Set方法;Maybe的类型具有不确定性,犹如他的名字一样,它可能返回bool也可能返回无值。
Object的例子中,我试图设置一个key的值,其返回一个Maybe ,不确定是否成功使用FromJust()来处理;
Maybe 有以下判断数据的成员函数:

|

IsNothing()

是否具有值

IsJust()

| 与IsNothing()结果相反 | |

FromJust()

| 返回本体值,没有则触发程序奔溃 | |

FromMaybe()

| 返回本体值,没有则返回默认值 |

资源

v8 入门文档
node 扩展文档
v8 文档

总结

能看出,对数据的操作,都是在c++基础之上,借助v8的规则,运转规则;但是相对而言操作比较繁琐;