看到这个标题,可能有些人会认为奇怪——Object不是JS的根本数据类型么,有什么实现不实现的呢?如不雅你这么想的话,解释你没有接触过其它说话,一向都是在和JS打交道,编程世界那么大年夜,你没有出去看一看。C/C++/Java等说话是没有这种json的数据类型的,其它一些有的:如在Pthyon琅绫擎叫做字典,在Ruby/Perl琅绫擎叫散列表,当然这只是个名称罢了,本质上可以算作json类型。而C是“万物之母”,C琅绫擎没有的,就得经由过程某种方法实现。
在说Map之前,Object还稀有字类型的属性没有评论辩论。
并且JS琅绫擎的Object是若何查找属性的,这个问题有人说是经由过程遍历key的字符串查找的,也有人说是经由过程哈希查找的。毕竟它是怎么存储和查找的,能不克不及把Object算作一个map来应用?如不雅无法大年夜源码的角度实际地看一下浏览器的实现,你的不雅点可能就站不住脚,只能吠形吠声。
Chrome自行开辟了V8引擎,并被Node拿去当解析器。本文精晓过V8的源码测验测验分析Object的实现。
1. V8的代码构造
v8的源码位于 src/v8/src/ ,代码层级比拟较较简单,然则实现比较复杂,为了能看懂,须要找到一个切入点,经由过程打断点、加log等方法肯定则个切入点是对的,如不雅这个抱病不是关键的点,进行到某一步的时刻就断了,那么竽暌股这个点出发测验测验去找其它的点。赓续验证,最后找到一个最关键的处所,由这个处所由浅入深地扩大到其它处所,最后形成一个别系。
以下,先解释JS Object的类图。
先来看一下,它是怎么查找的:
2. JS Object类图
V8琅绫擎所有的数据类型的根父类都是Object,Object派生HeapObject,供给存储根本功能,往下的JSReceiver用于原型查找,再往下的JSObject就是JS琅绫擎的Object,Array/Function/Date等持续于JSObject。左边的FixedArray是实际存储数据的处所。
3. 创建JSObject
有了这个map的对象之后,用它来创建一个JSObect:
在创建一个JSObject之前,会先把读到的Object的文本属性序列化成 constant_properties ,如下的data:
- var data = {
- name: "yin",
- age: 18,
- "-school-": "high school"
- };
会被序列成:
- ../../v8/src/runtime/runtime-literals.cc 72 constant_properties:
- 0xdf9ed2aed19: [FixedArray]
- – length: 6
- [0]: 0x1b5ec69833d1
- [1]: 0xdf9ed2aec51
- [2]: 0xdf9ed2aec71
- [3]: 18
- [4]: 0xdf9ed2aec91
- [5]: 0xdf9ed2aecb1
它是一个FixedArray,一共有6个元素,因为data总共是有3个属性,每个属性有一个key和一个value,所以Array就有6个。第一个元素是第一个key,第二个元素是第一个value,第三个元素是第二个key,第四个元素是第二个key,依次类推。Object供给了一个Print()的函数,把它用来打印对象的信息异常有赞助。膳绫擎的输出有两种类型的数据,一种是String类型,第二种是整型类型的。
FixedArray是V8实现的一个类似于数组的类,它表示一段持续的内存,膳绫擎的FixedArray的length = 6,那么它占的内存大年夜小将是:
- length * kPointerSize
因为它存的都是对象的指针(或者直接是整型数据类型,如膳绫擎的18),在64位的操作体系上,一个指针为8个字节,它的大年夜小将是48个字节。它记录了一个初始的内存开端地址,应用元素index乘以指针大年夜小作为偏移,加上开端地址,就可以取到响应index的元素,这和数组是一样的事理。只是V8本身封装了一个,便利添加一些自定义的函数。
- Handle map = ComputeObjectLiteralMap(context, constant_properties,
- &is_result_from_cache);
把这个申请后的Map打印出来: