[Effective JavaScript 笔记]第46条:使用数组而不要使用字典来存储有序集合
对象属性无序性
js对象是一个无序属性集合。
var obj={};
obj.a=10;
obj.b=30;
属性a和属性b并没有谁前谁后之说。for...in循环,先输出哪个属性都有可能。
获取和设置不同的属性与顺序无关,都会以大致相同的效率产生相同的结果。
也就是说访问属性a和访问属性b,没有哪个访问更快之说。ES标准并未规定属性存储的任何特定顺序,甚至于枚举对象也未涉及。for...in循环会挑选一定的顺序来枚举对象的属性,标准允许js引擎自由选择一个顺序,它们的选择会微妙地改变程序行为。
如要求一个对象表示一个从字符串到值的有序映射,创建一个有序的报表。
function report(highScores){
var res='';
var i=1;
for(var name in highScores){
res+=i+'. '+highScores[name].name+':'+highScores[name].points+'\n';
i++;
}
return res;
}
report([{name:'张三',points:1110111},
{name:'李四',points:1110102},
{name:'王五',points:1110911}]);
/*预期的结果
"1. 张三:1110111
2. 李四:1110102
3. 王五:1110911
"
*//*实际的结果 chrome,ff,ie
"1. 张三:1110111
2. 李四:1110102
3. 王五:1110911
"
*/
上面代码在测试的几个环境中表现顺序和索引相符,但一些其它的环境可以选择以不同的顺序来存储和枚举对象的属性,所以report有可能导致产生不同的字符串,得到不正确的报表。
程序对对象枚举的顺序依赖并不是显式地。如果没有在多个js环境中测试过你的代码,那么你的程序有可能因为for...in循环的不同输出而导致改变。
依赖数据顺序
如果对于数据结构中的条目顺序有强依赖,那么就优先考虑数组而不是字典。如上面的report函数如果接收的是一个数组而不是一个对象,那么可以用for来循环,可以保证在所有环境顺序都是一致正确的。
function report(highScores){
var res='';
for(var i=0,n=highScores.length;i < n;i++){
var score=highScores[i];
res+=(i+1)+'. '+score.name+':'+score.points+'\n';
}
return res;
}
report([{name:'张三',points:1110111},
{name:'李四',points:1110102},
{name:'王五',points:1110911}]);
//"1. 张三:1110111
2. 李四:1110102
3. 王五:1110911
"
通过接收一个对象数组,每个对象包含有name和points属性,上面的代码可以按0~highScores.length-1的顺序遍历所有的元素。
浮点型运算
假设有一个映射标题和等级的电影字典。
var ratings={
'Good Will Hunting':0.8,
'Mystic River':0.7,
'21':0.6,
'Doubt':0.9
};
浮点型算术运算的四舍五入会导致对计算顺序依赖。详细见《第2条:理解JavaScript的浮点数》。当组合未定义顺序的枚举时,可能会导致循环不可预知。
var total=0,count=0;
for(var key in ratings){
total+=ratings[key];
count++;
}
total/=count;
total;//chrome里:0.7499999999999999
在流行的js环境实际上使用不同的顺序执行这个循环。一些环境按照下面的顺序来枚举对象的key,得到下面这个值。
(0.8+0.7+0.6+0.9)/4 //0.75
有些环境总是先枚举潜在的数组索引,然后才是其他key。电影21是可以作为数组的索引的整数值,它首先被枚举,得到下面的结果。
(0.6+0.8+0.7+0.9)/4 //0.7499999999999999
可以看到上面的chrome就是先枚举潜在的数组索引。
整数计算浮点型
对于浮点数的计算,可以把浮点数转化为整数,然后再转化回浮点数。整数的计算顺序可以是任意顺序的。所以对象的属性值的列举顺序并不重要。代码如下
(8+7+6+9)/4/10 //0.75
(6+8+7+9)/4/10 //0.75
提示
使用for...in循环来枚举对象属性应当与顺序无关
如果聚集运算字典中的数据,确保聚集操作与顺序无关
使用数组而不是字典来存储有序集合
[Effective JavaScript 笔记]第46条:使用数组而不要使用字典来存储有序集合的更多相关文章
- [Effective JavaScript 笔记]第49条:数组迭代要优先使用for循环而不是for...in循环
示例 下面代码中mean的输出值是多少? var scores=[98,74,85,77,93,100,89]; var total=0; for(var score in scores){ tota ...
- [Effective JavaScript 笔记]第52条:数组字面量优于数组构造函数
js的优雅很大程序要归功于程序中常见的构造块(Object,Function及Array)的简明的字面量语法.字面量是一种表示数组的优雅方法. var a=[1,2,3,5,7,8]; 也可以使用构造 ...
- [Effective JavaScript 笔记]第5章:数组和字典--个人总结
前言 这节里其实一直都在讨论对象这个在js中的万能的数据结构.对象可以表式为多种的形式,表示为字典和数组之间的区别.更多的我觉得这章讨论多的是一些对应实现功能的相关操作,有可能出现的bug以及如何避免 ...
- [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象
js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...
- [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符
“1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...
- [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码
函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...
- [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法
js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...
- [Effective JavaScript 笔记]第58条:区分数组对象和类数组对象
示例 设想有两个不同类的API.第一个是位向量:有序的位集合 var bits=new BitVector(); bits.enable(4); bits.enable([1,3,8,17]); bi ...
- [Effective JavaScript 笔记]第66条:使用计数器来执行并行操作
第63条建议使用工具函数downloadAllAsync接收一个URL数组并下载所有文件,结果返回一个存储了文件内容的数组,每个URL对应一个字符串.downloadAllAsync并不只有清理嵌套回 ...
随机推荐
- sql server 使用函数辅助查询
函数是所有语言系统下都具备的内部数据处理过程,SQL SERVER也同样内置了许多函数.在SQL SERVER中,函数是由一个或多个T-SQL语句组成的子程序.利用函数可以简化数据的处理操作. 函数分 ...
- mysql使用基础 sql语句与数据完整性(二)
二.DML:Data Manipulation Language 数据操作语言 作用:操作表中的数据的. 关键:INSERT UPDATE DELETE 注意:日期或字符串.字符要使用单引号引起来. ...
- 取当前的地址栏的Url和url中的参数
看到这样一段代码: exports.showLogin = function (req, res) { req.session._loginReferer = req.headers.referer; ...
- (好文推荐)一篇文章看懂JavaScript作用域链
闭包和作用域链是JavaScript中比较重要的概念,首先,看看几段简单的代码. 代码1: var name = "stephenchan"; var age = 23; func ...
- abstract和接口
接口只包含常量和抽象方法,不能实例化. abstract: 1.抽象类不能实例化, 2.可以没有抽象方法.但有了抽象方法,一定要被定义为抽象类. 3.子类没有实现父类中所有的抽象方法.子类也必须定义为 ...
- overlay-2
<script src="/jquery.js"></script><script type="text/javascript"& ...
- 用form表单实现Ajax---post提交
实例讲解:新闻发布实现无刷新上传,显示 html代码: 注意:文本框中并没有id ,,只有name.jquery获取每个文本框的值还要在拼写提交格式(id=value&name=value& ...
- Linux使用
RedHat5 [cat] 将一个文件内容加入到另外一个另外一个文件中 参数 -n 或 --number 由 1 开始对所有输出的行数编号 -b 或 --number-nonblank 和 -n 相似 ...
- 判断Set里的元素是否重复、==、equals、hashCode方法研究-代码演示
被测试类,没有重写hasCode()和equals()方法: package niukewang; import java.util.Objects; public class setClass { ...
- python_元组
元组 元组是用圆括号括起来的,其中的元素之间用逗号隔开.(都是英文半角) >>># 变量引用 str >>> s = "abc" >> ...