JavaScript数组与字典的混用陷阱及高性能遍历指南

作者:霁月

时间:2026-10-26

浏览:624

本文解析JavaScript中数组兼具字典特性的现象,演示如何通过for in遍历对象属性。重点指出使用for in遍历数组的性能缺陷,推荐采用缓存length属性的经典for循环以获得最佳执行效率,并深入探讨length属性对数组截断与扩展的影响机制。

文章目录

JavaScript数组与字典的混用特性

在JavaScript中,Array类型不仅具备数组的功能,还表现出字典(Dictionary)的行为特征。首先通过具体示例展示数组的基础使用方式。

代码实现如下:

var a = new Array();
a[0] = "Acer";
a[1] = "Dell";
for (var i = 0; i < a.length; i++) {
alert(a[i]);
}

接下来介绍字典模式的使用场景。


代码实现如下:

var computer_price = new Array();
computer_price["Acer"] = 500;
computer_price["Dell"] = 600;
alert(computer_price["Acer"]);

我们可以沿用上述数组遍历的方式,对该字典结构进行迭代处理。


代码实现如下:

for (var i in computer_price) {
alert(i + ": " + computer_price[i]);
}

在此循环中,变量i代表字典中的每个键名。程序输出结果如下:


Acer: 500


Dell: 600



此外,computer_price作为一个字典对象,其每个键值实际上对应于该对象的一个属性。例如,Acer即为computer_price的一个属性。因此可以采用以下方式访问:


computer_price.Acer



下面介绍字典与数组的简写声明语法。


var array = [1, 2, 3]; // 数组


var array2 = { "Acer": 500, "Dell": 600 }; // 字典


alert(array2.Acer); // 500


这种字典声明方式与前文逻辑一致。在示例中,Acer既是键值,也可视为字典对象的属性。



对象属性遍历方法

进一步探讨如何遍历普通对象的属性,可以使用for in语句实现。


代码实现如下:

function Computer(brand, price) {
this.brand = brand;
this.price = price;
}
var mycomputer = new Computer("Acer", 500);
for (var prop in mycomputer) {
alert("computer[" + prop + "]=" + mycomputer[prop]);
}

上述代码中,Computer构造函数包含brand和price两个属性,因此输出结果为:


computer[brand]=Acer


computer[price]=500


这种用法有助于探查对象包含的所有属性。若已知Computer对象存在brand属性,可通过以下方式获取属性值:


mycomputer.brand


或 mycomputer[brand]


以提取具体数值。


总结:JavaScript中的数组可兼作字典使用,字典的键值即对应对象的属性。遍历对象属性时,for in语句是常用手段。



数组遍历的性能陷阱与优化方案

数组遍历与属性访问


尽管JavaScript中数组本质上是对象,但并无充分理由使用for in循环来遍历数组。


相反,存在诸多理由避免使用for in遍历数组。


注意:JavaScript中的数组并非关联数组。


JavaScript仅通过对象来管理键值对应关系,而关联数组具有有序性,对象则无序。


由于for in循环会枚举原型链上的所有属性,必须借助hasOwnProperty函数进行过滤,


这导致其执行速度比普通for循环慢许多倍。


遍历策略


为实现数组遍历的最佳性能,强烈建议采用经典的for循环结构。


代码实现如下:

var list = [1, 2, 3, 4, 5, ...... 100000000];
for(var i = 0, l = list.length; i < l; i++) {
console.log(list[i]);
}

上述代码包含一个优化技巧,即通过变量l缓存数组长度。


虽然length是数组的一个属性,但在每次循环中重复访问它仍会产生性能开销。


尽管最新的JavaScript引擎可能对此进行了优化,但无法保证代码始终运行在具备这些优化的环境中。


实际上,不缓存数组长度的写法比缓存版本慢得多。


length属性的截断与扩展机制

length属性机制


length属性的getter方法直接返回数组长度,而setter方法会截断数组。


代码实现如下:

var foo = [1, 2, 3, 4, 5, 6];
foo.length = 3;
foo; // [1, 2, 3]
foo.length = 6;
foo; // [1, 2, 3]

译者注:


在Firebug中查看此时foo的值显示为: [1, 2, 3, undefined, undefined, undefined]


但该结果并不完全准确,若在Chrome控制台查看foo,结果表现为: [1, 2, 3]


因为在JavaScript中undefined是一个变量而非关键字,上述两种显示结果的含义存在本质差异。


// 译者注:为验证这一点,执行以下代码以检查序号5是否存在于foo中。


5 in foo; // 无论Firebug还是Chrome均返回false


foo[5] = undefined;


5 in foo; // 无论Firebug还是Chrome均返回true


将length设置为更小的值会截断数组,但增大length属性值不会对数组内容产生任何影响。


结论


为了获得更佳性能,推荐使用普通for循环并缓存数组的length属性。


使用for in遍历数组被视为不良编码习惯,容易引发错误并导致性能问题。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章