上文中,我们已经编译成功了V8,在模拟器上成功运行了脚本,还弹出了结果。
本文简单分析一下代码。熟悉一下代码结构。
http://cnodejs.org/blog/?p=1621 这篇文章写的不错,帮我弄明白了不少东西。
HandleScope handle_scope;
HandleScope就是变量作用域的概念,一个大括号的区间。当你创建一个scope以后,所有的创建的变量都会加入到这个scope,直到出现一个新的scope,或者这个scope被delete掉。写个大概的示例代码,这是伪代码,并不能运行。
HandleScope scope; // 类似{
Handle<Integer> num = Integer::New(5); // 类似 num=5;作用域在scope
HandleScope scope2; // 类似{
Handle<Integer> num2 = Integer::New(5); // 类似 num2=5;作用域在scope2
scope2.Close(num2); // 类似}
Handle<Integer> num3 = Integer::New(5); // num3=5;作用域在scope
scope.Close(num3);
对于出了scope的变量进行访问,将会得到Undefined结果。
对于context的部分还没有弄明白,貌似是类似scope的作用域概念,还有local和Persistent等区别。我简单尝试不使用context,并改为local运行时出错,有待观察。从源代码的注释看,local是使用已经存在的context,而persistent则是重新创建了个作用域。
就我的理解,scope虽然管理内部对象的释放,但是没有办法添加对象,context才是添加对象的地方。
Handle<String> source = String::New("'Hello V8'");
Handle<Script> script = Script::Compile(source);
Handle<Value> result = script->Run();
这三句比较容易理解。
source就是脚本代码,也可以从js文件中读取。
Script是通过source代码转换成的二进制脚本,Compile和New是两种不同的方式,new的方式为context无关。但是刚才的context范围我本身也没有搞明白,所以同样等待观察。
Value这个类是V8在C++中映射JS数据类型的类。V8还封装了其他几个基本数据类,Interge, String等,继承关系也和JS中一致。
最初的解释就是这样子。下面给作用域添加一些对象,并用脚本访问。
在source语句前加上这么两句,在context中创建了一个String类型的变量。
Handle<String> world = String::New("V8");
context->Global()->Set(String::New("world"), world);
然后把source改为
Handle<String> source = String::New("'Hello '+world");
弹出的提示仍然为Hello V8,没办法,谁让这里的世界只有V8呐。
再尝试下,JS中非常方便的对象,可以动态添加属性等等。
把我们的世界再改变一下吧。
Handle<Object> world = Object::New();
world->Set(String::New("Mar"), String::New("V8"));
world->Set(String::New("Moon"), Integer::New(123));
context->Global()->Set(String::New("world"), world);
Handle<String> source = String::New("'Hello '+world.Mar+' '+world.Moon"); // 运行结果是hello V8 123
我们这个世界的火星属于V8。一个Object的对象,自由的添加属性。
下节,要添加一个自己定义的C函数到js中去。