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 相关文章推荐
原型方法的不同写法居然会影响调试的解决方法
Mar 08 Javascript
javascript学习随笔(使用window和frame)的技巧
Mar 08 Javascript
js简单实现用户注册信息的校验代码
Nov 15 Javascript
ActiveX控件与Javascript之间的交互示例
Jun 04 Javascript
JavaScript中的闭包(Closure)详细介绍
Dec 30 Javascript
jQuery大于号(&gt;)选择器的作用解释
Jan 13 Javascript
angularJS Provider、factory、service详解及实例代码
Sep 21 Javascript
JS区分Object与Aarry的六种方法总结
Feb 27 Javascript
Vue响应式原理详解
Apr 18 Javascript
Vue实现自定义下拉菜单功能
Jul 16 Javascript
8 个有用的JS技巧(推荐)
Jul 03 Javascript
vue瀑布流组件实现上拉加载更多
Mar 10 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隐形一句话后门,和ThinkPHP框架加密码程序(base64_decode)
2011/11/02 PHP
免费手机号码归属地API查询接口和PHP使用实例分享
2014/04/10 PHP
PHP 二维关联数组根据其中一个字段排序(推荐)
2017/04/04 PHP
PHP 返回数组后处理方法(开户成功后弹窗提示)
2017/07/03 PHP
PHP实现动态删除XML数据的方法示例
2018/03/30 PHP
关于Jquery操作Cookie取值错误的解决方法
2013/08/26 Javascript
JS获得浏览器版本和操作系统版本的例子
2014/05/13 Javascript
Javascript封装DOMContentLoaded事件实例
2014/06/12 Javascript
JavaScript实现图片滑动切换的代码示例分享
2016/03/06 Javascript
nodejs中解决异步嵌套循环和循环嵌套异步的问题
2017/07/12 NodeJs
Dropify.js图片宽高自适应的方法
2017/11/27 Javascript
angular2路由之routerLinkActive指令【推荐】
2018/05/30 Javascript
详解微信小程序开发用户授权登陆
2019/04/24 Javascript
JavaScript表格隔行变色和Tab标签页特效示例【附jQuery版】
2019/07/11 jQuery
vue实现全匹配搜索列表内容
2019/09/26 Javascript
Javascript中的this,bind和that使用实例
2019/12/05 Javascript
[01:22:10]Ti4 循环赛第二日 DK vs Empire
2014/07/11 DOTA
Python中用Decorator来简化元编程的教程
2015/04/13 Python
Python正则表达式和元字符详解
2018/11/29 Python
python中while和for的区别总结
2019/06/28 Python
python3.x+pyqt5实现主窗口状态栏里(嵌入)显示进度条功能
2019/07/04 Python
Python 日志logging模块用法简单示例
2019/10/18 Python
django连接mysql数据库及建表操作实例详解
2019/12/10 Python
通过python实现windows桌面截图代码实例
2020/01/17 Python
冰淇淋店创业计划书范文
2013/12/27 职场文书
《跨越百年的美丽》教学反思
2014/02/11 职场文书
2014年检验员工作总结
2014/11/19 职场文书
五年级下册复习计划
2015/01/19 职场文书
常务副总经理岗位职责
2015/02/02 职场文书
高中英语教学反思范文
2016/03/02 职场文书
强烈推荐:小学生:暑假作息时间表(值得收藏)
2019/07/09 职场文书
python爬取新闻门户网站的示例
2021/04/25 Python
django上传文件的三种方式
2021/04/29 Python
防止web项目中的SQL注入
2021/12/06 MySQL
日本动漫十大公认神作:第五现已全网禁播,《死亡笔记》在榜
2022/03/18 日漫
DSP接收机前端设想
2022/04/05 无线电