JS数组内部性能

1.数组内部

数组是一种特殊的对象。使用方括号来访问属性 arr[0] 实际上是来自于对象的语法。它其实于 obj[key] 相同,其中 arr 是对象,而数字用作键(key)。

它们扩展了对象,提供了特殊的方法来处理有序的数据集合以及 length 属性。但从本质上讲,它仍然是一个对象。

记住,在 JavaScript 中只有 8 种基本的数据类型。数组是一个对象,因此其行为也像一个对象。

例如,它是通过引用来复制的:

let fruits = ["Banana"];

let arr = fruits;    //通过引用复制(两个变量引用同一个数组)

alert(arr === fruits);    //true

arr.push("Pear");    //通过引用修改数组

alert(fruits);    //Banana, Pera

......但是数组真正特殊的是它们的内部实现。JavaScript 引擎尝试把这些元素一个接一个地存储在连续的内存区域,而且还有一些其它的优化,以使数组运行得非常快。

但是,如果我们不像”有序集合“那样使用数组,而是像常规对象那样使用数组,这些优化将不生效。

例如,从技术上讲,我们可以这样做:

let fruits = [];    //创建一个数组

fruits[99999] = 5;    //分配索引远大于数组长度的属性

fruits.age = 25;    //创建一个具有任意名称的属性

这是可以的,因为数组是基于对象的。我们可以给它们添加任何属性。

但是 JavaScript 引擎会发现,我们在像使用常规对象一样使用数组,那么针对数组的优化就不再适用了,然后对应的优化就会被关闭,这些优化所带来的优势也就荡然无存了。

数组误用的几种方式:

1.添加一个非数字的属性,比如 arr.test = 5.

2.制造空洞,比如:添加 arr[0],然后添加 arr[1000](它们中间什么都没有)。

3.以倒序填充数组,比如 arr[1000], arr[999]等等。


请将数组是为作用于 有序数据 的特殊结构。它们为此提供了特殊的方法。数组在 JavaScript 引擎内部是经过特殊调整的,是的更好地作用于连续的有序数据,所以请以正确的方式使用数组。如果你需要任意键值,那很有可能实际上你需要的是常规对象{}。


2.数组性能

shift/unshift

push/pop 方法运行的比较快,而 shift/unshift 比较慢。



为什么作用于数组的末端会比首端快呢?让我们看看在执行期间都发生了什么:

fruits.shift();    //从首端取出一个元素

只获取并移除键值为 0 对应的元素是不够的。其它元素也需要被重新编号。

shift 操作必须做三件事:

1.移除索引为 0 的元素。

2.把所有的元素向左移动,把索引 1 改成 02 改成 1 以此类推,对其重新编号。

3.更新 length 属性。


shift操作

数组里的元素越多,移动它们就要花越多的时间,也就意味着越多的内存操作。

unshift 也是一样:为了在数组的首端添加元素,我们首先需要将现有的元素向右移动,增加它们的索引值。


push/pop

push/pop 是什么样的呢?它们不需要移动任何东西。如果从末端移除一个元素,pop 方法只需要清理索引值并缩短 length 就可以了。

pop 操作的行为:

fruits.pop();    //从末端取走一个元素


pop操作

pop 方法不需要移动任何东西,因为其它元素都保留了各自的索引。这就是为什么 pop 会特别快。

push 方法也是一样的。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容