javascript for循环从入门到偏门(效率优化+奇特用法)


Posted in Javascript onAugust 01, 2012

一,for循环的基本写法
代码如下:

//例一for(var i=1;i<=10;i++) { 
alert(i); 
}

这段代码太简单了,我都不好意思拿出手。代码的执行结果是依次弹出1到10,PS:在早期的IE如IE6中,你把10改成10000,就能让用户一直点确定什么也不能干了哈哈——不要说是我出的主意。
由于这是一篇基础课程,所以我们回归正题来详细分析一下这段代码吧。
for循环的结构都是类似的,任意一个for循环都是这样的:
for(开始前;循环进行的条件;循环一次结束后做什么) {
// 主体代码
}如果仔细看一下for循环,就会发现他的一个万年不变的特点:for后的()中,永远是有且只有两个;(英文分号)!
上面的结构代码已经说明,分号的作用是用来分割for循环的执行条件。这些条件都是缺一不可的,可以为空,但位置必须留着,所以必须有两个;。
开始前:一般用来声明一些变量,如例一的var i=0,就像准备了一个篓子,里面暂时没有任何东西。工具的数量不限,你可以在for循环开始前声明100个变量,除了不好看之外,也没什么问题。
循环进行的条件:如第1个例子中的i<10,就是条件了,只有条件为真时,for循环才会进行下去,例一的条件可以看成if(i<10){//do...}。可以想象成篓子最多装10个东西,如果多了10个,就不装了,退出循环。
循环一次后做什么:例一中只是简单的给篓子里面加入一个东西,其实你还可以做很多事,毕竟循环一次不容易。
特别说明:for循环“开始前”的代码只会执行一次,不会影响整个for循环的效率,而“进行条件”与“一次结束后做什么”,你循环次数有多少,他就执行多少次,所以他们经常成为for循环性能瓶颈。
如果说for循环第1个;前是开始前做的事,那我可不可以把开始前的事情拿到for循环前面来呢?只要在开始前定义就行了嘛。答案是可以:
//例2 
var i=0; 
for(;i<10;i++) { 
alert(i); 
}

但要注意,虽然for后面的括号里“开始前”已经没有内容了,但;(分号)还在!而且必须在!
同理,既然第2个;后面的代码是一次结束后执行的,那我也可以把要执行的放在for循环后啊。如下:
//例子3 
var i=0; 
for(;i<10;) { 
alert(i); 
i++ 
}

但依然,万恶的两个;还是必须存在。
上面也就是两个基础的“偏门用法”了。。。不要说我坑爹
不过你也看到了,执行循环的条件,是不能单独提出来的,必须放在两个分号之间!前后夹击!
二,for循环的偏门写法
1,我们把例一的代码变成:
var i=0;
for(;i<10;alert(i++)) ;怎么样?这才是坑爹啊,{}都没有了!不过完全正确啊!
不过这种写法太过逆天,第2个;后面的代码最好不要多,一多起来你就不能掌握i的值了,而且因为代码混乱可能导致人为的语法错误。
适用环境:
简单的for循环操作,比如造一个元素依次是从1到1000的数字的这么一个数组,就用这招,酷就一个字。
2,深入分析
通过前面的例子我们知道,其实for循环的执行条件就是判断一个布尔值,就像这样:
var t = true; 
if(t == true) { 
alert('啊!') 
}

这个if语句没人看不懂吧,其实还可以这样写:
var t = true; 
if(t) { 
alert('啊!') 
}

效果是一样的,如果for循环的进行条件就是判断布尔值,那下面这种写法理解起来就不困难了:
var i = 10; 
for(;i;i--){ 
alert(i); 
}

这段代码的效果是依次弹出10到1(和例一反过来了)。其中for循环的进行条件简单的要死,就是个i.但根据我们前面的解说,其实条件是这样的:
if(i) { 
//do 
}

也就是i为真的情况,就继续执行循环。这个for循环的i什么时候为真呢,只要i不等于0,空字符串,undefined,null,false时,就都为真。
所以此for循环一直会执行,直到i=0,就结束了。但我们代码中不会看到0 ,迷惑新手,装B利器。
3,又一个
先看代码,来自园友snandy:
var ary = ["jack","tom","lily","andy"]; 
for(var i=0,a;a=ary[i++];){ 
console.log(a); 
}

依然是注意看for循环的进行条件:a=ary[i++]。特别注意这里是=而不是==,要是==的话循环就没法进行了。
这个条件判断很扯,我也比较晕。类似于:
if(a=b) {...} //注意是=!
此时如果b是false,那就会返回false了。
回到上面的例子中,如果i++加出了头,那ary[i++]就是false值了(null,undefined都算),所以条件就成了false,所以循环就断了。
这个例子局限很大,snandy也提到了,比如你数组中就是有个0,那也可能会导致循环终结。
4,jQuery的一个写法
function sibling( elem ) { 
var r = [], 
n = elem.parentNode.firstChild; 
for ( ; n; n = n.nextSibling ) { 
if ( n.nodeType === 1 && n !== elem ) { 
r.push( n ); 
} 
} 
return r; 
}

这是从jquery里提取的获得兄弟节点的办法,他有一个奇特的for循环。循环进行的条件是判断n是否为真。由于n一直是一个html节点,所以一直为真。而每次循环结束后都会把n的下一个节点赋给n,而当n的下一个节点没有时,n就成了false,终结循环。
小结:
从上面所有的例子可以看到,任他千奇百怪的for循环,都离不开两个;。大家想看懂一个for循环的原理,直接以;为界线分割for循环即可,一目了然。
三,for循环的效率优化
1,缓存变量
这也是最常用的效率优化办法:
var arr =[1,2,23,...,1000]; 
for(var i=0,l = arr.length;i<l;i++) { 
// 
}

由于执行条件每次循环都要判断,所以如果每次循环都从arr中读取length的话,无疑很浪费而且必然增加计算次数,造成效率浪费。
2,倒序法
比如一个数组有1000个元素,如果不考虑提取顺序,那么可以倒序循环:
var arr =[1,2,23,...,1000]; 
var i = arr.length; 
for(;i>0;i--){ 
//alert(i); 
}

为什么倒序会比顺序效率快?没有科学道理啊!其实只是因为倒序可以少用一个变量(对比下上一个例子吧),除开这点,两者没有速度差别。
3,注意跳出
不进行不必要的操作,这是基本逻辑。如有1000个li里面,有一个li上有个特殊的className,我们要找出这个li。那么,由于已经确定只有一个这样的li,我们找到这个li就应该马上跳出,break,下面的循环就没必要进行了。这样一来,由于li有999/1000的几率不是最后一个,我们肯定能节约不少计算。
其他情况请举一反三。
4,使用偏门用法
上面我介绍的偏门用法不只是写出来好看的,大部分都有节约变量节约计算的效果,能用就用,既酷又有效,何乐而不为呢?
----------------------------总结--------------------------------
我喜欢Javascript的灵活,不仅仅是因为可以用来装酷。希望在博客园学到更多的JS知识,大牛们的文章我经常看,收益良多。下面是一些我找到的在园子里的牛人,不全,没有列出来者不要诅咒我。
cloudgamer,司徒正美,汤姆大叔,snandy以及其他太低调的高手。想找他们的博客直接搜索吧。
PS:实在是喜欢博客园的插入代码功能,以后涉及到大量代码的文章都直接发博客园吧。
不要尝试下面的代码:
var arr =[1,2,23,1000]; 
for(var i=0,l = arr.length;i<l;) { 
if(arr[i]>10000) { 
i++; 
} 
}
Javascript 相关文章推荐
使用javascript访问XML数据的实例
Dec 27 Javascript
JavaScript 关键字屏蔽实现函数
Aug 02 Javascript
Js 中debug方式
Feb 07 Javascript
Js 时间函数getYear()的使用问题探讨
Apr 01 Javascript
JavaScript 作用域链解析
Nov 13 Javascript
jQuery基于muipicker实现仿ios时间选择
Feb 22 Javascript
自学实现angularjs依赖注入
Dec 20 Javascript
原生js仿淘宝网商品放大镜效果
Feb 28 Javascript
ReactNative踩坑之配置调试端口的解决方法
Jul 28 Javascript
webpack进阶——缓存与独立打包的用法
Aug 02 Javascript
Vue组件间数据传递的方式(3种)
Jul 13 Javascript
antd Select下拉菜单动态添加option里的内容操作
Nov 02 Javascript
jQuery源码中的chunker 正则过滤符分析
Jul 31 #Javascript
关于jquery ajax 调用带参数的webservice返回XML数据一个小细节
Jul 31 #Javascript
基于jquery的点击链接插入链接内容的代码
Jul 31 #Javascript
基于jQuery实现的百度导航li拖放排列效果,即时更新数据库
Jul 31 #Javascript
基于jQuery的动态增删改查表格信息,可左键/右键提示(原创自Zjmainstay)
Jul 31 #Javascript
jQuery.each()用法分享
Jul 31 #Javascript
artDialog 4.1.5 Dreamweaver代码提示/补全插件 附下载
Jul 31 #Javascript
You might like
php下MYSQL limit的优化
2008/01/10 PHP
兼容性最强的PHP生成缩略图的函数代码(修改版)
2011/01/18 PHP
PHP按一定比例压缩图片的方法
2018/10/12 PHP
解决extjs在firefox中关闭窗口再打开后iframe中js函数访问不到的问题
2008/11/06 Javascript
js 与或运算符 || &amp;&amp; 妙用
2009/12/09 Javascript
jquery 仿QQ校友的DIV模拟窗口效果源码
2010/03/24 Javascript
jquery.cvtooltip.js 基于jquery的气泡提示插件
2010/11/19 Javascript
js自动闭合html标签(自动补全html标记)
2012/10/04 Javascript
Jquery操作radio的简单实例
2014/01/06 Javascript
通过JS来动态的修改url,实现对url的增删查改
2014/09/01 Javascript
jQuery层动画定位滑动效果的方法
2015/04/30 Javascript
javascript中DOM复选框选择用法实例
2015/05/14 Javascript
基于JavaScript实现轮播图代码
2016/07/14 Javascript
AngularJS基础 ng-class-odd 指令示例
2016/08/01 Javascript
js验证手机号、密码、短信验证码代码工具类
2020/06/24 Javascript
vue下跨域设置的相关介绍
2017/08/26 Javascript
如何在vue里添加好看的lottie动画
2018/08/02 Javascript
Vue 表情包输入组件的实现代码
2019/01/21 Javascript
layui实现二维码弹窗、并下载到本地的方法
2019/09/25 Javascript
javascript使用链接跨域下载图片
2019/11/01 Javascript
Python实现的弹球小游戏示例
2017/08/01 Python
基于OpenCV python3实现证件照换背景的方法
2019/03/22 Python
pyenv虚拟环境管理python多版本和软件库的方法
2019/12/26 Python
使用Python爬虫库requests发送表单数据和JSON数据
2020/01/25 Python
微信html5页面调用第三方位置导航的示例
2018/03/14 HTML / CSS
HTML5中的websocket实现直播功能
2018/05/21 HTML / CSS
size?丹麦官网:英国伦敦的球鞋精品店
2019/04/15 全球购物
EJB的角色和三个对象
2015/12/31 面试题
自愿离婚协议书范文2014
2014/10/12 职场文书
工作检讨书怎么写
2015/01/23 职场文书
酒店服务员岗位职责
2015/02/09 职场文书
2016年寒假社会实践活动总结
2015/10/10 职场文书
《我在为谁工作》:工作的质量往往决定生活的质量
2019/12/27 职场文书
python实现图片九宫格分割的示例
2021/04/25 Python
golang http使用踩过的坑与填坑指南
2021/04/27 Golang
一次SQL查询优化原理分析(900W+数据从17s到300ms)
2022/06/10 SQL Server