这种模式的问题在于每次循环迭代的时候都要访问数据的长度。这样会使代码变慢,特别是当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. SPIR-V*:面向 OpenCL™ 工作负载的英特尔® 显卡编译器默认接口

    英特尔® 显卡编译器最近从 SPIR* 转换到 SPIR-V*,作为面向 OpenCL™ 工作负载的中间表示.这看起来像编译器的内部变化,对用户来说不可见,但是这展示了我们支持 Khronos* 开放 ...

  2. Beta阶段事后分析

    1. 设想和目标 1.1 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们在Beta阶段任务主要分为两部分,一类是对原功能的扩展,一类是新的博文功能.我们通过规 ...

  3. linux第三章学习笔记

    第三章 进程管理 进程是Unix操作系统抽象概念中最基本的一种. 进程管理是所有操作系统的心脏所在. 一.进程 1. 进程是处于执行期的程序.除了可执行程序代码,还包括打开的文件.挂起的信号.内核内部 ...

  4. 20135202闫佳歆--week3 构造一个简单的Linux系统MenuOs--学习笔记

    此为个人学习笔记存档 week 3 构造一个简单的Linux系统MenuOs 复习: 计算机有三个法宝:存储程序计算机,函数调用堆栈,中断 操作系统有两把剑: 1.中断上下文的切换,保存现场和恢复现场 ...

  5. Leetcode题库——40.组合总和II

    @author: ZZQ @software: PyCharm @file: combinationSum2.py @time: 2018/11/15 18:38 要求:给定一个数组 candidat ...

  6. Access restriction: The type 'BASE64Decoder' is not API

    Access restriction: The type 'BASE64Decoder' is not API (restriction on required library 'C:\Program ...

  7. C# Stopwatch获取循环中某操作的时间消耗

    在C#中通常使用DateTime来表示当前时间,可以在一个操作的前后分别使用一个DateTime对象获取当前时间,再将两个DateTime对象相减获得时间差(TimeSpan对象),从而得到这个操作耗 ...

  8. PSP(3.23——3.29)以及周记录

    3.23 9:30 10:30 15 45 Android Studio 界面设计学习 A Y min 13:00 13:15 0 15 站立会议 A Y min 23:20 23:45 0 25 英 ...

  9. java自定义注解学习(三)_注解解析及应用

    上篇文章已经介绍了注解的基本构成信息.这篇文章,主要介绍注解的解析.毕竟你只声明了注解,是没有用的.需要进行解析.主要就是利用反射机制在运行时进行查看和利用这些信息 常用方法汇总 在Class.Fie ...

  10. XShell中文乱码问题解决

    现象:XShell终端中输入中文显示乱码 原因:XShell终端的编码格式与服务器不同 解决:修改XShell终端的编码格式:菜单中点击,文件->属性->终端->编码,选择“UTF- ...