JS是一门基于对象的语言,比如JS中的函数,对象,数组等。JS中的函数是一等公民,可以将函数定义为变量,函数可以入参,也可以返回新函数。对象在运行时可以动态修改其内容,所以JS语言非常灵活。
JS对象
JS实现继承的方式:在对象中的原型链中添加属性,把继承的属性通过原型链链接起来。JS对象就是由一组组属性和值构成的对象集合。JS对象的值有三种类型:
- 原始类型:本身值无法改变。主要包括null, undefined, boolean, number, string, symbol七种。
- 对象类型。
- 函数类型。
V8内部如何实现函数的调用
函数调用时,在V8内部会为函数对象添加两个隐藏属性:name属性和code属性,如下图所示:

如果函数是匿名函数,则name值为anonymous,code为函数代码,以字符串的形式存储在内存中。当执行到一个函数时,V8就会从函数对象中取出code属性值,也就是函数代码,然后解释执行这段函数代码。
JS函数执行的过程中,V8会维护一个作用域链,如果函数中使用了某个变量,会先在函数内部查找,如果没有会继续沿着作用域链去外部作用域中查找。这种将外部变量和函数绑定的技术就叫闭包。

V8是怎样提升对象属性的访问速度
ECMAScript规范中定义数字属性按照索引值大小升序排列,字符串属性根据创建时的顺序升序排列。对象中的数字属性成为排序属性,V8中称其为elements;字符串属性称为常规属性,V8中称其为properties。

分解成elements和properties两种线性数据解构后,如果执行索引操作,V8会先从elements属性中按照顺序读取所有的元素,然后在properties属性中读取所有元素,这样就完成了一次索引操作。
V8采用一个权衡的策略来加快属性查找的效率,这个策略是将部分常规属性直接存储到对象本身,成为对象内属性。

不过对象内属性数量是固定的,默认10个,如果超出则它们依然会被保存到常规属性存储中。保存在线性数据结构中的属性称为”快属性“。线性数据结构中只需要通过索引就可以访问到属性。
如果一个对象的属性过多,V8会采用另外一种存储策略:”慢属性“策略。慢属性的对象内部会有独立的非线性数据结构(词典)作为属性存储容器。所有的属性元信息不再是线性存储的,而是直接保存在属性字典中。

chrome中查看对象布局
chrome中查看对象的内存快照如下图:

总结
JS中的对象是由键值对组成的,如果以一个字典来存储,则读取效率会非常低。为了提升查找效率,V8引入了排序属性elements和常规属性properties。
在elements对象中,会按照顺序存放排序属性。 在properties对象中,会按照创建时间保存常规属性。
当常规属性少于一定数量时,V8会将该属性直接写入到对象中,节省中间步骤;如果对象的属性过多,V8就会降级为非线性的字典存储模式。