这种模式的问题在于每次循环迭代的时候都要访问数据的长度。这样会使代码变慢,特别是当myarray不是数据,而是HTML容器对象时。

HTML容器是DOM方法返回的对象,如:
document.getElementsByName()
document.getElementsByClassName()
document.getElementsByTagName()
还有很多其他HTML容器,他们在DOM标准以前就引入了,并一直使用至今。包括(除此之外还有很多):
docuement.images
页面上所有的IMG元素。
document.links
页面的A元素
document.forms
所有的froms。
document.forms[0].elements
页面上第一个from内的所有字段

容器的麻烦在于他们在document(HTML页面)下是活动的查询。也就是说,每次访问任何容器的长度时,也就是在查询活动的DOM操作时非常耗时的。

这就是为什么好的for循环模式是将已经遍历过的数组(或容器)的长度缓存起来。如以下代码所示。
for (var i = 0; max = myarray.length; i++) {
//对myarray[i]进行处理
}
这种方式下,对长度的值只提取一次,但应用到整个循环中。

在所有的浏览器中,通过将HTML容器上需要遍历的次数缓存起来都会大大提高速度。其中在Safari 3中速度会提高两倍,而在Ie7种会提高170倍。
注意,当要在循环中修改容器时(例如新增一个DOM元素),需要修改容器的长度。
function looper() {
var i = 0,
max,
myarray = [];

//...

for (i = 0, max = myarray.length; i < max; i++) {
//处理myarray[i]
}
}

这种模式的好处在于一致性,因为他贯穿了单一变量的模式。至缺陷在于创建代码时粘贴和复制整个循环比较麻烦。例如,如果要从一个函数复制循环至另一个函数,必须确保能将i和max携带至新函数中(如果这几个量在原函数中不再需要,则很可能会删掉他们了)。

对于循环的最后一个改进是,用i++代替以下两种表达式:
i = i + 1;
i += 1;

JsJLint推荐这样做,原因++和--提倡“excessive trickiness”,如果不同意这种说法,
可以将JsLint操作的plusplus设成flase(默认为真)。

for 模式中的两个变量引出了一些细微操作,原因是:
1.使用了最少的变量(而非最多)
2.逐步渐至0,这样通常更快,因为同0比较比同数组的长度比较,或同非0数组比较更有效率。

第一个修改后的模式是:
var i, myarray = [];
//注意要添加;号,这个是省略了第三个参数而已
for (i = myarray.length; i--;) {
//处理myarray[i]
}

第二个使用while循环:
var myarray = [],
i = myarray.length;

while (i--) {
//处理myarray[i]
}

for-in循环

for-in 循环应该用来遍历非数组对象。使用for-in循环也被称为枚举(enumeration);
从技术上来说,也可以使用for-in循环来遍历数组 (因为JavaScript中,数组也是对象),但是不推荐用户这样使用,因为当该数组对象已经被自定义函数扩大后,这样做有可能会导致逻辑上的错误。因此推荐使用正常的for循环来处理数组,并使用for-in循环来处理对象。

请考虑如下例子:

//对象
var man = {
hands: 2,
legs: 2,
heads: 1
};
//代码的其他部分
//将一个方法添加到所有对象上
if (typeof Object.prototype.clone === "undefined") {
Object.prototype.clone = function() {};
}

在本例子中,使用文本定义了一个简单的名为man的对象。在man对象定义前面或者后面的其他位置,使用了一个名为clone()的所有的方法来增加Object的原型。该原型链式活动的,这也就意味着所有的对象都会自动获取针对新方法的访问。为了避免在枚举man的方法时枚举出clone()方法,需要调用hasOwnPorperty()函数来过滤该原型属性。如果不使用过滤函数来进行过滤,将会显示出clone(),这在大多数情况下是不希望得到的结果。
//1.
//for-in循环
for (var i in man) {
if (man.hasOwnProperty(i )) {
console.log(i, ":", man[i]);
}
}
/
hands: 2
legs: 2
heads: 1
/

//2.
//反模式:
//不使用hasOwnProperty()进行检查后使用for-in循环的结果
for (var i in man) {
console.log(i, ":", man[i]);
}

/
控制台中的结果
hands: 2
legs: 2
heads: 1
clone: function()
/

另外一种使用hasOwnPorperty()的模式是在Object.ptototype中调用该函数,如下所示:

for (var i in man) {
if (Object.prototype.hasOwnProperty.call(man, i )) { //过滤
console.log(i, ":", man[i]);
}
}

在使用hasOwnProperty对man对象进行精炼后,可以有效的避免命名冲突,也可以使用一个本地变量来缓存比较长的属性如下所示:

var i,
hasOwn = Object.prototype.hasOwnProperty;
for (i in man) {
if (hasOwn.call(man, i)) { //过滤
console.log(i, ":", man[i]);
}
}

就for循环VS for-in循环的更多相关文章

  1. sqlserver中的循环遍历(普通循环和游标循环)

    sql 经常用到循环,下面介绍一下普通循环和游标循环 1.首先需要一个测试表数据Student

  2. Javascript基础系列之(六)循环语句(for循环)

    如果您希望一遍又一遍地运行相同的代码,并且每次的值都不同,那么使用循环是很方便的. document.write(cars[0] + "<br>"); document ...

  3. Oracle PL/SQL中的循环处理(sql for循环)

    今天来说下Oracle中的循环迭代处理,因为从自己的博客统计中看到,不少网友都搜索了关键字"SQL FOR循环",所以打算在这里说下个人的理解. PL/SQL也和我们常用的编程语言 ...

  4. 循环嵌套,while循环,穷举迭代循环

    一.循环嵌套 简单的就是说,在一个for循环里嵌入多个小for循环. 其中,在打矩形.三角形和乘法口诀表之类的题目中,大for循环一般表示的是行数,其余的小for循环式每一行中的内容. 二.while ...

  5. jQuery中each的用法之退出循环和结束本次循环

    jQuery中each的用法之退出循环和结束本次循环 jQuery中each类似于javascript的for循环 但不同于for循环的是在each里面不能使用break结束循环,也不能使用conti ...

  6. 慕课网-安卓工程师初养成-4-14 Java 循环语句之多重循环

    来源:http://www.imooc.com/code/1497 循环体中包含循环语句的结构称为多重循环.三种循环语句可以自身嵌套,也可以相互嵌套,最常见的就是二重循环.在二重循环中,外层循环每执行 ...

  7. Java 循环语句之多重循环

    循环体中包含循环语句的结构称为多重循环.三种循环语句可以自身嵌套,也可以相互嵌套,最常见的就是二重循环.在二重循环中,外层循环每执行一次,内层循环要执行一圈. 如下所示: 例如:使用 * 打印长方形: ...

  8. §12 循环101-while循环

    §12   循环101-while循环 While和for具有一定的可替换性.语法如下: while test body continue终止当次循环,break退出整个循环. 注意while之后要用 ...

  9. swift基本用法-for循环遍历,遍历字典,循环生成数组

    // Playground - noun: a place where people can play import UIKit //--------------------------------- ...

  10. JavaScript循环之for/in循环

    今天学到了JavaScript的语句篇.同其他常见编程语言如C.Java等一样,JavaScript中的语句包含:①表达式语句②复合语句和空语句③声明语句④条件语句⑤循环语句⑥跳转语句,当然JavaS ...

随机推荐

  1. SVN回退版本

    执行svn up 命令 保证当前本地版本是最新的版本. svn up 执行svn log 命令,查看历史修改,确定需要回复的版本,如果想要对比2个不同版本的文件差异 可以使用命令 svn diff - ...

  2. Apache Ignite 学习笔记(四): Ignite缓存冗余备份策略

    Ignite的数据网格是围绕着基于内存的分布式key/value存储能力打造的.当初技术选型的时候,决定用Ignite也是因为虽然同样是key/value存储,它有着和其他key/value存储系统不 ...

  3. kubeadm安装kubernetes 1.13.1集群完整部署记录

    k8s是什么 Kubernetes简称为k8s,它是 Google 开源的容器集群管理系统.在 Docker 技术的基础上,为容器化的应用提供部署运行.资源调度.服务发现和动态伸缩等一系列完整功能,提 ...

  4. MSSQL批量写入数据方案

    近来有一个项目Feature需要有批量写入数据的场景,正巧整理资料发现自己以前也类似实现的项目,在重构的同时把相关资料做了一个简单的梳理,方便大家参考. 循环写入(简单粗暴,毕业设计就这样干的)(不推 ...

  5. Android中应用contentprovider来创建数据库的一些步骤

    http://blog.csdn.net/xiaodongvtion/article/details/7865669 1:首先创建一个xxprovider的class,它是extendscontent ...

  6. PowerTeam--Alpha阶段个人贡献分及转会人员

    PowerTeam--Alpha阶段个人贡献分 我们的团队共有6人,总分300分. 经团队成员通过个人申请以及组内投票的方式,最终的等级评定如下面的等级评定矩阵所示:   β1 β2 β3 γ1 γ2 ...

  7. LINUX内核分析第一周学习总结——计算机是如何工作的

    LINUX内核分析第一周学习总结——计算机是如何工作的 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/course/ ...

  8. “数学口袋精灵”App的第一个Sprint计划(总结)

    “数学口袋精灵”App的第一个Sprint计划 ——11.20  星期五(第十天)第一次Sprint计划结束   第一阶段Sprint的目标以及完成情况: 时间:11月11号~11月20号(10天) ...

  9. 四则运算生成程序——GUI支持和部分功能改进

    项目成员:张金生     张政 工程地址: https://coding.net/u/jx8zjs/p/paperOne/git ssh://git@git.coding.net:jx8zjs/pap ...

  10. clear & file input & reset & file input

    clear & file input & reset & file input Clear <input type="file"> docume ...