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 相关文章推荐
JS event使用方法详解
Apr 28 Javascript
Span元素的width属性无效果原因及解决方案
Jan 15 Javascript
基于jquery的地址栏射击游戏代码
Mar 10 Javascript
jQuery随机密码生成的方法
Mar 09 Javascript
JavaScript判断一个字符串是否包含指定子字符串的方法
Mar 18 Javascript
jquery ajax双击div可直接修改div中的内容
Mar 04 Javascript
js一维数组、多维数组和对象的混合使用方法
Apr 03 Javascript
JS二叉树的简单实现方法示例
Apr 05 Javascript
获取url中用&amp;隔开的参数实例(分享)
May 28 Javascript
详解vue 自定义组件使用v-model 及探究其中原理
Oct 11 Javascript
vue实现评论列表功能
Oct 25 Javascript
JS函数本身的作用域实例分析
Mar 16 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 curl模拟post提交数据示例
2013/12/31 PHP
PHP将Excel导入数据库及数据库数据导出至Excel的方法
2015/06/24 PHP
基于ThinkPHP实现批量删除
2015/12/18 PHP
php实现图片缩略图的方法
2016/03/29 PHP
pjblog修改技巧汇总
2007/03/12 Javascript
jQuery 使用个人心得
2009/02/26 Javascript
javascript 异步页面查询实现代码(asp.net)
2010/05/26 Javascript
基于jQuery的history历史记录插件
2010/12/11 Javascript
jQuery的控件及事件(输入控件及回车事件)使用示例
2013/07/25 Javascript
javascript阻止浏览器后退事件防止误操作清空表单
2013/11/22 Javascript
javascript获取隐藏元素(display:none)的高度和宽度的方法
2014/06/06 Javascript
Nodejs学习笔记之入门篇
2015/04/16 NodeJs
JS+CSS实现带小三角指引的滑动门效果
2015/09/22 Javascript
javascript函数命名的三种方式及区别介绍
2016/03/22 Javascript
Sequelize中用group by进行分组聚合查询
2016/12/12 Javascript
详解如何给React-Router添加路由页面切换时的过渡动画
2019/04/25 Javascript
浅入深出Vue之组件使用
2019/07/11 Javascript
javascript中call,apply,callee,caller用法实例分析
2019/07/24 Javascript
在vue-cli 3中给stylus、sass样式传入共享的全局变量
2019/08/12 Javascript
跟老齐学Python之赋值,简单也不简单
2014/09/24 Python
详解Python读取配置文件模块ConfigParser
2017/05/11 Python
在pycharm中设置显示行数的方法
2019/01/16 Python
jupyter notebook 添加kernel permission denied的操作
2020/04/21 Python
利用4行Python代码监测每一行程序的运行时间和空间消耗
2020/04/22 Python
PyCharm MySQL可视化Database配置过程图解
2020/06/09 Python
Python datetime模块的使用示例
2021/02/02 Python
HTML5中的拖放实现详解
2017/08/23 HTML / CSS
世界上最大的罕见唱片、CD和音乐纪念品网上商店:991.com
2018/05/03 全球购物
Hashtable 添加内容的方式有哪几种,有什么区别?
2012/04/08 面试题
初中优秀学生评语
2014/12/29 职场文书
毕业生党员个人总结
2015/02/14 职场文书
自主招生自荐信格式
2015/03/04 职场文书
安全生产警示教育活动总结
2015/05/09 职场文书
课程设计感想范文
2015/08/11 职场文书
教师培训学习心得体会
2016/01/21 职场文书
nginx容器方式反向代理实战
2022/04/18 Servers