自制JSON解析库C++(一)--对JavaScript对象的理解

版权声明:本文为博主原创文章,转载请在文章开头给出原文链接。 https://blog.csdn.net/xiyanggudao/article/details/52294702

JSON只有两种结构:键值对和数组;它们之间可以相互嵌套,形成树形结构,叶子节点有字符串、数字、false、true、null。

在这之前,首先谈谈对JavaScript核心思想的理解:

在JS的世界里,没有类,只有对象,对象怎么来,通过动态添加属性和方法造出来。

没有类很麻烦,假如多个地方要用到类似的对象,就得造多次。

JS有办法,一是通过方法造,造好了返回,方法像是工厂,也像C++的构造函数;二是通过原型造,也是设计模式中的原型模式,原型既是对象,也是对象的模具。

JS里的方法和C++不一样,方法也是对象,更像C++的可调用对象。语法上所有对象都可以调用,方法也可以为自己添加属性,方法也可以赋值给属性,本质上对象、方法、属性没有区别。

JS里的new相当于创建空对象,以该对象绑定为函数的this,然后调用函数的过程。

虽然说在JS里一切皆对象,整个程序也是一个全局对象(全局函数),但是有几个比较特殊的:字符串、数值、true、false、null、undefined、NaN,这些都是不可变对象。其中字符串、数值、true/false有包装对象String、Number、Boolean。其实在JS中当做对象使用时会进行包装处理(null、undefined除外),访问字符串、数值、true/false的属性时,其实是访问了String、Number、Boolean临时对象的属性,即使对其属性赋值也不会影响它的状态。

JSON是JavaScript对象的字符串表示,JavaScript有内置的方法eval可以解析(或者JSON.parse、JSON.stringify),所以JSON和JavaScript对象是有对应关系的。

既然这样,如果要写一个C++的JSON解析库,那么C++端也应该有对JavaScript对象进行抽象的实体类,表示JSON解析的结果,也表示所有的JavaScript对象,暂且命名为js::Object。

解析的接口也不标新立异了,和JavaScript保持一致,定为js::JSON::parse、js::JSON::stringify。不用eval,因为eval不只针对JSON,而是可以解析任何JavaScript语句。

对于上面的特殊对象字符串、数值、true/false、null、undefined、NaN,C++端需要单独考虑,可以进行显式解包装,在js::Object提供toString、toBoolean之类的方法。但是从另一方面考虑,js::Object是对JavaScript所有实体的抽象,而toString之类的方法只是提供向C++类型转换的方便,是不是将toString之类的方法放在一个工具类里会更好呢?工具类暂且命名为JsObjectToCppType。

上面的特殊对象字符串、数值、true/false、null、undefined、NaN,都是不可变对象,可以有改变其属性的语句,虽然不会有错误和异常,但不会产生效果,这点在C++端如何模拟?容易想到的是继承,特殊对象继承js::Object,然后重写一些实现,但是这会带来一些问题。因为多态只能通过引用和指针实现,将解析的结果以引用的方式返回是不好的,返回堆对象指针又会有内存管理的问题,对这种轻量级的对象使用智能指针感觉不太好,也会增加复杂度。考虑下JavaScript的多态,其实是利用了动态语言可以动态改变对象的属性和方法的特性,那么C++也可以在js::Object中使用动态方法,首先将js::Object的构造函数设为私有,通过工厂函数设置动态方法构造不同的js::Object。

对象属性的访问,JavaScript的属性访问方式有两种,object.property和object[property],前一种“.”运算符在C++中不能被重载且C++不支持动态属性,所以解析库只模拟后一种。

猜你喜欢

转载自blog.csdn.net/xiyanggudao/article/details/52294702