跟我学习javascript的for循环和for...in循环


Posted in Javascript onNovember 18, 2015

大家都知道在JavaScript中提供了两种方式迭代对象:

  • for 循环;
  • for..in循环;

一、for循环

不足:

在于每次循环的时候数组的长度都要去获取;
终止条件要明确;
在for循环中,你可以循环取得数组或是数组类似对象的值,譬如arguments和HTMLCollection对象。通常的循环形式如下:

// 次佳的循环
for (var i = 0; i < myarray.length; i++) {
 // 使用myarray[i]做点什么
}

这种形式的循环的不足在于每次循环的时候数组的长度都要去获取下。这回降低你的代码性能,尤其当myarray不是数组,而是一个HTMLCollection对象的时候。

HTMLCollections指的是DOM方法返回的对象,例如:

document.getElementsByName()
document.getElementsByClassName()
document.getElementsByTagName()

还有其他一些HTMLCollections,这些是在DOM标准之前引进并且现在还在使用的。有:

document.images: 页面上所有的图片元素
document.links : 所有a标签元素
document.forms : 所有表单
document.forms[0].elements : 页面上第一个表单中的所有域

集合的麻烦在于它们实时查询基本文档(HTML页面)。这意味着每次你访问任何集合的长度,你要实时查询DOM,而DOM操作一般都是比较昂贵的。

这就是为什么当你循环获取值时,缓存数组(或集合)的长度是比较好的形式,正如下面代码显示的:

for (var i = 0, max = myarray.length; i < max; i++) {
 // 使用myarray[i]做点什么
}

这样,在这个循环过程中,你只检索了一次长度值。

在所有浏览器下,循环获取内容时缓存HTMLCollections的长度是更快的,2倍(Safari3)到190倍(IE7)之间。//此数据貌似很老

注意到,当你明确想要修改循环中的集合的时候(例如,添加更多的DOM元素),你可能更喜欢长度更新而不是常量。

伴随着单var形式,你可以把变量从循环中提出来,就像下面这样:

function looper() {
 var i = 0,
  max,
  myarray = [];
 // ...
 for (i = 0, max = myarray.length; i < max; i++) {
  // 使用myarray[i]做点什么
 }
}

这种形式具有一致性的好处,因为你坚持了单一var形式。不足在于当重构代码的时候,复制和粘贴整个循环有点困难。例如,你从一个函数复制了一个循环到另一个函数,你不得不去确定你能够把i和max引入新的函数(如果在这里没有用的话,很有可能你要从原函数中把它们删掉)。

最后一个需要对循环进行调整的是使用下面表达式之一来替换i++。

i = i + 1
i += 1

JSLint提示您这样做,原因是++和?-促进了“过分棘手(excessive trickiness)”。如果你直接无视它,JSLint的plusplus选项会是false(默认是default)。

两种变化的形式:

  • 少了一个变量(无max)
  • 向下数到0,通常更快,因为和0做比较要比和数组长度或是其他不是0的东西作比较更有效率01
//第一种变化的形式:

var i, myarray = [];
for (i = myarray.length; i?-;) {
 // 使用myarray[i]做点什么
}

//第二种使用while循环:

var myarray = [],
 i = myarray.length;
while (i?-) {
 // 使用myarray[i]做点什么
}

这些小的改进只体现在性能上,此外JSLint会对使用i?-加以抱怨。

二、for …in 循环—也被称为“枚举”

for …in 循环经常用来迭代对象的属性或数组的每个元素,for…in循环中的循环计数器是字符串,而不是数字。它包含当前属性的名称或当前数组元素的索引。 下面直接上几个例子:

当遍历一个对象的时候,变量 i 也就是循环计数器 为 对象的属性名 :

//使用for..in循环遍历对象属性 
varperson={ 
 name: "Admin", 
 age: 21, 
 address:"shandong" 
}; 
for(var i in person){ 
 console.log(i); 
}

执行结果为:

name

age

address

当遍历一个数组的时候,变量 i 也就是循环计数器 为 当前数组元素的索引 :

//使用for..in循环遍历数组 
vararray = ["admin","manager","db"] 
for(vari in array){ 
 console.log(i); 
}

执行结果:

0

1

2

但是,现在看来for .. in循环还挺好用啊,不过,别高兴太早,看看下面的例子:

var array =["admin","manager","db"]; 
//给Array的原型添加一个name属性 
Array.prototype.name= "zhangsan"; 
for(var i in array){ 
 alert(array[i]); 
}

运行结果:

admin

manager

db

zhangsan
咦,奇观了,怎么平白无故的冒出来一个zhangsan
现在,再看看使用 for循环会怎样?

vararray = ["admin","manager","db"]; 
//给Array的原型添加一个name属性 
Array.prototype.name = "zhangsan"; 
for(var i =0 ; i<array.length; i++){ 
 alert(array[i]); 
};

运行结果:

admin

manager

db
哦, 现在明白了,for..in循环会把某个类型的原型(prototype)中方法与属性给遍历出来,所以这可能会导致代码中出现意外的错误。为了避免这个问题,我们可以使用对象的hasOwnProperty()方法来避免这个问题,如果对象的属性或方法是非继承的,那么hasOwnProperty() 方法返回true。即这里的检查不涉及从其他对象继承的属性和方法,只会检查在特定对象自身中直接创建的属性。

vararray = ["admin","manager","db"]; 
Array.prototype.name= "zhangshan"; 
for(var i in array){ 
//如果不是该对象自身直接创建的属性(也就是该属//性是原型中的属性),则跳过显示 
 if(array.hasOwnProperty(i)){ 
  alert(array[i]); 
  }
}

运行结果:

admin

manager

db
另外一种使用hasOwnProperty()的形式是取消Object.prototype上的方法。像这样:

// 对象
var man = {
 hands: 2,
 legs: 2,
 heads: 1
};
for (var i in man) {
 if (Object.prototype.hasOwnProperty.call(man, i)) { // 过滤
  console.log(i, ":", man[i]);
 }
}

其好处在于在man对象重新定义hasOwnProperty情况下避免命名冲突。也避免了长属性查找对象的所有方法,你可以使用局部变量“缓存”它。

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

严格来说,不使用hasOwnProperty()并不是一个错误。根据任务以及你对代码的自信程度,你可以跳过它以提高些许的循环速度。但是当你对当前对象内容(和其原型链)不确定的时候,添加hasOwnProperty()更加保险些。

格式化的变化(通不过JSLint)会直接忽略掉花括号,把if语句放到同一行上。其优点在于循环语句读起来就像一个完整的想法(每个元素都有一个自己的属性”X”,使用”X”干点什么):

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

以上就是介绍了JavaScript提供的两种方式迭代对象:for循环和for...in循环,希望这篇文章对大家的学习有所帮助。

Javascript 相关文章推荐
eval的两组性能测试数据
Aug 17 Javascript
A标签触发onclick事件而不跳转的多种解决方法
Jun 27 Javascript
JS如何将数字类型转化为没3个一个逗号的金钱格式
Jan 27 Javascript
JavaScript Math.ceil 方法(对数值向上取整)
Jan 09 Javascript
Javascript中的匿名函数与封装介绍
Mar 15 Javascript
jQuery定义背景动态切换效果的方法
Mar 23 Javascript
每天一篇javascript学习小结(String对象)
Nov 18 Javascript
给angular加上动画效遇到的问题总结
Feb 17 Javascript
JS中使用变量保存arguments对象的方法
Jun 03 Javascript
AngularJs ng-repeat 嵌套如何获取外层$index
Sep 21 Javascript
Base64(二进制)图片编码解析及在各种浏览器的兼容性处理
Feb 09 Javascript
vue.js整合vux中的上拉加载下拉刷新实例教程
Jan 09 Javascript
js实现模拟银行卡账号输入显示效果
Nov 18 #Javascript
跟我学习javascript的prototype原型和原型链
Nov 18 #Javascript
超精准的javascript验证身份证号的具体实现方法
Nov 18 #Javascript
javascript中checkbox使用方法简单实例演示
Nov 17 #Javascript
javascript下拉列表中显示树形菜单的实现方法
Nov 17 #Javascript
JS封装cookie操作函数实例(设置、读取、删除)
Nov 17 #Javascript
jquery可定制的在线UEditor编辑器
Nov 17 #Javascript
You might like
PHP实现数组根据某个字段进行水平合并,横向合并案例分析
2019/10/08 PHP
php高性能日志系统 seaslog 的安装与使用方法分析
2020/02/29 PHP
xml 封装与解析(javascript和C#中)
2009/07/26 Javascript
神奇的7个jQuery 3D插件整理
2011/01/06 Javascript
jQuery判断checkbox是否选中的小例子
2013/12/02 Javascript
js使用循环清空某个div中的input标签值
2014/09/29 Javascript
javascript实现复选框选中属性
2015/03/25 Javascript
JQuery插件jcarousellite的参数中文说明
2015/05/11 Javascript
jquery实现根据浏览器窗口大小自动缩放图片的方法
2015/07/17 Javascript
JavaScript程序中的流程控制语句用法总结
2016/05/23 Javascript
JavaScript解析JSON格式数据的方法示例
2017/01/24 Javascript
windows下vue-cli及webpack搭建安装环境
2017/04/25 Javascript
JS获取短信验证码倒计时的实现代码
2017/05/22 Javascript
微信小程序实现滚动消息通知
2018/02/02 Javascript
从源码里了解vue中的nextTick的使用
2018/11/22 Javascript
vue项目初始化到登录login页面的示例
2019/10/31 Javascript
解决ant design vue 表格a-table二次封装,slots渲染的问题
2020/10/28 Javascript
[04:42]5分钟带你了解什么是DOTA2(第一期)
2017/02/07 DOTA
python插入数据到列表的方法
2015/04/30 Python
python实现员工管理系统
2018/01/11 Python
python+matplotlib演示电偶极子实例代码
2018/01/12 Python
Python 爬虫之Beautiful Soup模块使用指南
2018/07/05 Python
Python如何获得百度统计API的数据并发送邮件示例代码
2019/01/27 Python
wxPython色环电阻计算器
2019/11/18 Python
python3+opencv生成不规则黑白mask实例
2020/02/19 Python
Python 合并拼接字符串的方法
2020/07/28 Python
python+selenium 简易地疫情信息自动打卡签到功能的实现代码
2020/08/22 Python
Html5中的桌面通知Notification的实现
2018/09/25 HTML / CSS
医学专业本科毕业生自我鉴定
2013/12/28 职场文书
大二学生学习个人自我评价
2014/01/19 职场文书
2014年远程教育工作总结
2014/12/09 职场文书
2015年新农合工作总结
2015/03/30 职场文书
土木工程毕业答辩开场白
2015/05/29 职场文书
办公用品管理制度
2015/08/04 职场文书
班主任经验交流心得体会
2015/11/02 职场文书
Java 通过手写分布式雪花SnowFlake生成ID方法详解
2022/04/07 Java/Android