VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 11339|回复: 1

[分享] SpiderMonkey_31.2.0版编程笔记 五___对象操作一

[复制链接]
04_avatar_middle
online_vip 发表于 2015-9-16 08:46:10 | 显示全部楼层 |阅读模式
本帖最后由 liehuo 于 2015-9-17 08:44 编辑

我为什么说完了函数才说对象呢?我这样做只是为了对象做基础,因为一个对象可以有内部的成员变量,也可以有成员函数。如果直接把一个对象里添加函数你可能不知所措,说完了函数之后你就觉得顺其自然了。但是本贴不打算把函数添加到一个对象里去,还是先简单一点的好,只添加一个变量也就是对象的属性。要添加属性那么给谁添加,哪个对象?是不是应该先定义一个对象?定义对象的函数是JS_DefineObject,原型如下:
JSObject * JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, const JSClass *clasp, JSObject *proto, unsigned attrs)
参数cx就是哪个上下文,obj是属于哪个对象,可以理解为父对象,一般是global对象。name是创建的对象打算叫什么名字,clasp就是用哪个类创建新的对象,当然是JSClass的类型,这符合面向对象编程,因为对象就是类的实例。attrs就是创建对象所用到的属性,一般是JSPROP_ENUMERATE,JSPROP_READONLY,JSPROP_SHARED等等。上面的参数可以看出需要一个JSClass类型的类,那就先来个类吧:
JSClass my_class = {
        "MyClass",
        JSCLASS_HAS_PRIVATE,
        JS_PropertyStub,               //增加属性
        JS_DeletePropertyStub,    //删除属性
        getter,                                //获取属性
        setter,                                 //设置属性
        JS_EnumerateStub,
        JS_ResolveStub,
        JS_ConvertStub
};
你有没有注意这个类和那个全局对象所用的类除了第二行的flag不一样,还多了getter和setter两个回调函数。通过这两个函数就可以分别获取对象的属性和设置对象的属性。当然不填和全局对象的类一样也没事,当我们JS_DefineProperty定义属性的时候再添加也是可以的,甚至那时候不添加也不会有事情的。这就是为什么分两个帖子来解说对象的缘故。getter函数的接口原型是:
bool(* JSPropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp);
setter函数的接口原型是:
bool(* JSStrictPropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool strict, JS::MutableHandleValue vp);
所以你要实现这两个接口。我们的实现函数是:
bool getter(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp)
{
        jsval jv = vp.get();
        int b = JSVAL_TO_INT(jv);
        printf("get.vp:%d\n", b);;
        return true;
}
bool setter(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool strict, JS::MutableHandleValue vp)
{
        jsval jv = vp.get();
        int b = JSVAL_TO_INT(jv);
        printf("set.vp:%d\n", b);;
        return true;
}
不过要在my_class 的上面,因为这个类要用到这两个函数,不然会出错找不到这两个函数的。提前声明也是可以的。实现了这两个接口后你就可以定义对象和属性了。还是看源码吧:
  1. #include "stdafx.h"
  2. #include "include/jsapi.h"
  3. #pragma comment(lib,"lib/mozjs-31.lib")//这里直接用这种方式,是为了观看方便
  4. using namespace JS;
  5. static JSClass global_class = {
  6.         "global",
  7.         JSCLASS_GLOBAL_FLAGS,
  8.         JS_PropertyStub,          //增加属性
  9.         JS_DeletePropertyStub,    //删除属性
  10.         JS_PropertyStub,          //获取属性
  11.         JS_StrictPropertyStub,    //设置属性
  12.         JS_EnumerateStub,
  13.         JS_ResolveStub,
  14.         JS_ConvertStub
  15. };
  16. bool getter(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp)
  17. {
  18.         jsval jv = vp.get();
  19.         int b = JSVAL_TO_INT(jv);
  20.         printf("get.vp:%d\n", b);;
  21.         return true;
  22. }
  23. bool setter(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool strict, JS::MutableHandleValue vp)
  24. {
  25.         jsval jv = vp.get();
  26.         int b = JSVAL_TO_INT(jv);
  27.         printf("set.vp:%d\n", b);;
  28.         return true;
  29. }
  30. JSClass my_class = {
  31.         "MyClass",
  32.         JSCLASS_HAS_PRIVATE,
  33.         JS_PropertyStub,
  34.         JS_DeletePropertyStub,
  35.         getter,//nullptr,//(JSPropertyOp)GetPro,这样也行的
  36.         setter,//nullptr,//(JSStrictPropertyOp)SetPro,
  37.         JS_EnumerateStub,
  38.         JS_ResolveStub,
  39.         JS_ConvertStub
  40. };
  41. void ExecScript(JSContext *cx)
  42. {
  43.         JSObject *obj = JS_NewGlobalObject(cx, &global_class, nullptr, FireOnNewGlobalHook);//创建一个新的JS对象,用作一个全局对象,但是要被根化,这里没有被根化。
  44.         //RootedObject global(cx, JS_NewGlobalObject(cx, &global_class, nullptr, FireOnNewGlobalHook));//上面和下面的可以并作中间的这一句。分开写是为了循序渐进
  45.         RootedObject global(cx, obj);//在当前的上下文环境,用创建的全局对象创建根化的全局对象
  46.         JSAutoCompartment ac(cx, global);//进入新全局对象的隔室,好像干什么坏事总是见不得人,非要躲在包厢里做坏事一样
  47.         JS_InitStandardClasses(cx, global);//初始化全局对象和其它js里的常规对象

  48.         printf("*********************演示获取和设置普通js里的对象属性*********************\n");
  49.         char* script = "var student={name:'Zhangsan',age:30};";
  50.         const char *filename = "noname";
  51.         int lineno = 1;
  52.         bool ok = false;
  53.         ok = JS_EvaluateScript(cx, global, script, strlen(script), filename, lineno);//执行脚本
  54.         RootedValue rval(cx); //创建一个RootedValue变量用于接收执行的结果,而这个结果的值是一个被根化的值
  55.         JS_GetProperty(cx, global, "student", &rval);
  56.         if (rval.isObject())                     //判断是否是对象
  57.         {
  58.                 RootedObject stuObj(cx, JSVAL_TO_OBJECT(rval));
  59.                 JS_GetProperty(cx, stuObj, "age", &rval);//获取js里的对象属性的值;
  60.                 int age = JSVAL_TO_INT(rval);//将js里的整形变量转换为c++里的整形
  61.                 printf("student.age=%d\n", age);
  62.                 JS_GetProperty(cx, stuObj, "name", &rval);
  63.                 JSString *strName = rval.toString();
  64.                 printf("student.name=%s\n", JS_EncodeString(cx, strName));

  65.                 RootedValue setVal(cx);//这里再创建一个根化变量用于设置js里的对象属性值
  66.                 setVal.setInt32(99);
  67.                 JS_SetProperty(cx, stuObj, "age", setVal);//设置js里对象属性的值
  68.                 JSString *strname = JS_NewStringCopyN(cx, "Libai", strlen("Libai"));
  69.                 setVal.setString(strname);
  70.                 JS_SetProperty(cx, stuObj, "name", setVal);

  71.                 JS_GetProperty(cx, stuObj, "age", &rval);//再次调用函数获取js对象属性的值,看是否改变
  72.                 age = JSVAL_TO_INT(rval);
  73.                 printf("设置后student.age=%d\n", age);
  74.                 JS_GetProperty(cx, stuObj, "name", &rval);
  75.                 strName = rval.toString();
  76.                 printf("设置后student.name=%s\n", JS_EncodeString(cx, strName));
  77.         }
  78.         printf("************************自定义一个对象及其各操作**************************\n");
  79.         JSObject *Myobj = JS_DefineObject(cx, global, "myObject", &my_class, nullptr, JSPROP_ENUMERATE);
  80.         RootedObject rootMyobj(cx, Myobj);
  81.         rval.setInt32(185);
  82.         //定义一个属性,具有getter和setter方法,要求JSPropertyOp和JSStrictPropertyOp类型的函数
  83.         bool b = JS_DefineProperty(cx, rootMyobj, "shengao", rval, JSPROP_ENUMERATE, getter, setter);//这里把getter和setter设为nuuptr也行,因为在类里已经设置。
  84.         RootedValue rval2(cx);
  85.         JS_GetProperty(cx, global, "myObject", &rval2);
  86.         if (rval2.isObject())
  87.         {
  88.                 RootedValue rval3(cx);
  89.                 RootedObject stuObj2(cx, JSVAL_TO_OBJECT(rval2));
  90.                 JS_GetProperty(cx, stuObj2, "shengao", &rval3);//获取js里的对象属性的值;
  91.                 int num2 = JSVAL_TO_INT(rval3);//将js里的整形变量转换为c++里的整形
  92.                 printf("myObject.shengao=%d\n", num2);
  93.                 rval3.setInt32(175);
  94.                 JS_SetProperty(cx, stuObj2, "shengao", rval3);   //设置对象属性的值
  95.                 JS_GetProperty(cx, stuObj2, "shengao", &rval3);//获取js里的对象属性的值;
  96.                 num2 = JSVAL_TO_INT(rval3);//将js里的整形变量转换为c++里的整形
  97.                 printf("设置后myObject.shengao=%d\n", num2);
  98.         }
  99.         printf("\n");
  100. }
  101. int _tmain(int argc, _TCHAR* argv[])
  102. {
  103.         JS_Init();     //初始化JS引擎,一定要有这步,不然其它的操作都是扯淡
  104.         JSRuntime *rt = JS_NewRuntime(8L * 1024 * 1024, JS_USE_HELPER_THREADS);//创建运行时,是不是跟以前的不一样了
  105.         if (!rt)
  106.                 return 1;
  107.         JSContext *cx = JS_NewContext(rt, 8192);//创建一个JS上下文,与运行时关联起来
  108.         if (!cx)
  109.                 return 1;
  110.         //****************************************************************************************
  111.             ExecScript(cx);
  112.         //****************************************************************************************
  113.         JS_DestroyContext(cx);//销毁创建的上下文
  114.         JS_DestroyRuntime(rt);//销毁释放运行时
  115.         JS_ShutDown();        //释放js引擎使用的所有资源
  116.         return 0;
  117. }
复制代码

运行结果:
SpiderMonkey_31.2.0版编程笔记 五___对象操作一
运行之后我们发现getter和setter里的代码无非就是获取得到里面的数据,没有干什么,干脆去掉算了,只保留返回操作。于是改为:
  1. bool getter(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp)
  2. {
  3.         return true;
  4. }
  5. bool setter(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool strict, JS::MutableHandleValue vp)
  6. {
  7.         return true;
  8. }
复制代码

再次运行依然得到正确结果。再试着把类里的getter和setter,JS_DefineProperty函数里的getter和setter都设置为nullptr看看,是不是还是正常得到结果。这就证明JS_GetProperty和JS_SetProperty你设置了回调它就走回调,不设置它根本就不走这两个函数,照样能正确对对象操作。
上一篇:SpiderMonkey_31.2.0版编程笔记 四___函数操作二
下一篇:SpiderMonkey_31.2.0版编程笔记 六___对象操作二

评分

参与人数 1驿站币 +2 +2 收起 理由
51_avatar_small Syc + 2 + 2 赞一个!

查看全部评分





上一篇:SpiderMonkey_31.2.0版编程笔记 四___函数操作二
下一篇:SpiderMonkey_31.2.0版编程笔记 六___对象操作二
14_avatar_middle
在线会员 发表于 2015-11-17 16:18:13 | 显示全部楼层
感谢楼主的无私奉献。
您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

关闭

站长提醒上一条 /2 下一条

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号tongdun|网站地图wx_jqr

GMT+8, 2019-7-17 15:24

Powered by Discuz! X3.4

© 2009-2019 cctry.com

快速回复 返回顶部 返回列表