这种模式的问题在于每次循环迭代的时候都要访问数据的长度。这样会使代码变慢,特别是当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. 关于go v1.11安装后出现不能正常运行测试程序的问题

    本人最近安装go1.11后出现上述问题,没有找到原因,可能之前安装过的旧的版本在windows下环境变量设置出现了问题,修改后仍然无效,后来删除所有安装版本,及go环境变量,重新下载1.10版本进行安 ...

  2. error: Build input file cannot be found: '*******/node_modules/react-native/Libraries/WebSocket/libfishhook.a' 问题解决记录

    解决了刚才的'config.h' file not found问题,本以为就可以顺畅的跑起来,谁知道又被恶心到了,Build input file cannot be found!!! 问题: err ...

  3. djbc

    jdbc:mysql://localhost:3306:test这句里面分如下解析:jdbc:mysql:// 是指JDBC连接方式:localhost: 是指你的本机地址:3306 SQL数据库的端 ...

  4. 12.18daily_scrum

    本软件中的最后一个界面——“关于”界面的设计已经开始进行,数据传输的内容也差不多进行过半,最主要的任务依旧在测试过程中,我们组接下来还是要大力加强测试的强度和数量,注意边际数据和错误数据的测试处理: ...

  5. 【Alpha】第一次Scrum Meeting

    本次会议内容概括如下: 总结了一周以来大家任务的完成情况,对消耗时间进行统计,并评估了各自对团队的贡献(影响)程度 整理并融合所有人的工作的结果生成了相应的总结性文档 进一步明确了团队中各个成员的定位 ...

  6. 在centOS中安装mongodb

    自己在一个CentOS6.6的系统中按照官网的说明,走了一遍的安装过程,记录一下. 看过个mongo的视频,上面介绍的安装是用源码安装,而官网上说需要gcc4.8.3的版本,还有scons的编译工具, ...

  7. Sprint计划会议内容

    项目名称:蹭课神器 会议内容 首先我们讨论了项目的工作量及实施流程 一.工作认领 二.界面的总体规划 三.主要功能的设计 四.设计数据库 五.编写项目报告 六.软件测试和推广 然后我们进行了工作认领, ...

  8. 四种losses

    1. Classification losses 每次输入一个样本,对样本进行类别预测,根据预测类别和真实标签得到对应的分类损失. 2. Pairwise losses 每次输入两个样本,数据集包含了 ...

  9. 基于OVS的VLAN虚拟化简易实践方案

    基于OVS的VLAN虚拟化简易实践方案 前言 本实验基于ovs的vlan流表匹配,根据端口进行vlan标签插入.手工配置ovs,使其具有vlan虚拟化方案. 实验拓扑 ---- ---- | h1 | ...

  10. visual studio-2013之单元测试

    安装个vs把一个寝室搞得欲仙欲死的,,已经安装好了vs2013,那些欲仙欲死的事就都不说了.开始我们的正式作业——单元测试. 要做单元测试前提有: 1.要有Unit Test Generator工具 ...